Skip to content

Commit 020adb5

Browse files
committed
Fix type of clone expression
1 parent 38a7dfd commit 020adb5

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

src/Analyser/MutatingScope.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
use PHPStan\Type\NullType;
127127
use PHPStan\Type\ObjectShapeType;
128128
use PHPStan\Type\ObjectType;
129+
use PHPStan\Type\ObjectWithoutClassType;
129130
use PHPStan\Type\ParserNodeTypeToPHPStanType;
130131
use PHPStan\Type\StaticType;
131132
use PHPStan\Type\StringType;
@@ -1243,7 +1244,18 @@ private function resolveType(string $exprString, Expr $node): Type
12431244
}
12441245

12451246
if ($node instanceof Expr\Clone_) {
1246-
return $this->getType($node->expr);
1247+
$cloneType = TypeCombinator::intersect($this->getType($node->expr), new ObjectWithoutClassType());
1248+
1249+
return TypeTraverser::map($cloneType, static function (Type $type, callable $traverse): Type {
1250+
if ($type instanceof UnionType || $type instanceof IntersectionType) {
1251+
return $traverse($type);
1252+
}
1253+
if ($type instanceof ThisType) {
1254+
return new StaticType($type->getClassReflection(), $type->getSubtractedType());
1255+
}
1256+
1257+
return $type;
1258+
});
12471259
}
12481260

12491261
if ($node instanceof Node\Scalar\Int_) {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace CloneType;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
10+
public function doFoo(?object $object, $mixed): void
11+
{
12+
assertType('object', clone $object);
13+
assertType('object', clone $mixed);
14+
assertType('static(CloneType\\Foo)', clone new $this);
15+
assertType('static(CloneType\\Foo)', clone new static);
16+
assertType(self::class, clone new self);
17+
}
18+
19+
}

0 commit comments

Comments
 (0)