Skip to content

Commit 6766b2f

Browse files
committed
🐛 Narrow only by existing return types
Fixes a bug with mglaman#900 reported in https://www.drupal.org/project/experience_builder/issues/3539676 by @larowlan
1 parent 0328209 commit 6766b2f

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

src/Type/EntityIdNarrowedByNew.php

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
use PHPStan\Analyser\Scope;
99
use PHPStan\Reflection\MethodReflection;
1010
use PHPStan\Type\DynamicMethodReturnTypeExtension;
11-
use PHPStan\Type\IntegerType;
1211
use PHPStan\Type\NullType;
13-
use PHPStan\Type\StringType;
1412
use PHPStan\Type\Type;
15-
use PHPStan\Type\TypeCombinator;
13+
use PHPStan\Type\UnionType;
1614

1715
/**
1816
* @author Daniel Phin <[email protected]>
@@ -35,15 +33,15 @@ public function getTypeFromMethodCall(
3533
MethodCall $methodCall,
3634
Scope $scope
3735
): ?Type {
36+
// Usually contains a UnionType with IntegerType, StringType, NullType,
37+
// unless it was narrowed by a child.
38+
$originalReturnType = $methodReflection->getVariants()[0]->getReturnType();
3839
$isNewMethodCall = new MethodCall($methodCall->var, new Identifier('isNew'));
3940
if ($scope->getType($isNewMethodCall)->isFalse()->yes()) {
40-
return TypeCombinator::union(new IntegerType(), new StringType());
41+
// Remove NULL.
42+
return $originalReturnType->tryRemove(new NullType());
4143
}
4244

43-
return TypeCombinator::union(
44-
new IntegerType(),
45-
new StringType(),
46-
new NullType()
47-
);
45+
return $originalReturnType;
4846
}
4947
}

tests/src/Type/data/entity.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,12 @@
2828
assert($id3 instanceof NodeInterface);
2929
assert($id3->isNew() === FALSE);
3030
assertType('int|string', $id3->id());
31+
32+
class NarrowingId extends NodeInterface {
33+
public function id(): ?string {}
34+
}
35+
assert($idNarrowed1 instanceof NarrowingId);
36+
assertType('string|null', $idNarrowed1->id());
37+
assert($idNarrowed2 instanceof NarrowingId);
38+
assert($idNarrowed2->isNew() === FALSE);
39+
assertType('string', $idNarrowed2->id());

0 commit comments

Comments
 (0)