diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php index 318697ac4c..be7f04e1e4 100644 --- a/src/PhpDoc/TypeNodeResolver.php +++ b/src/PhpDoc/TypeNodeResolver.php @@ -384,7 +384,7 @@ private function resolveThisTypeNode(ThisTypeNode $typeNode, NameScope $nameScop private function resolveNullableTypeNode(NullableTypeNode $typeNode, NameScope $nameScope): Type { - return TypeCombinator::addNull($this->resolve($typeNode->type, $nameScope)); + return TypeCombinator::union($this->resolve($typeNode->type, $nameScope), new NullType()); } private function resolveUnionTypeNode(UnionTypeNode $typeNode, NameScope $nameScope): Type diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 8e2186cab3..ebc906aacb 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -786,6 +786,10 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6591.php'); } + if (PHP_VERSION_ID >= 80000) { + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6790.php'); + } + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6584.php'); } diff --git a/tests/PHPStan/Analyser/data/bug-6790.php b/tests/PHPStan/Analyser/data/bug-6790.php new file mode 100644 index 0000000000..68aa284b3b --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-6790.php @@ -0,0 +1,66 @@ += 8.0 + +namespace Bug6790; + +use function PHPStan\Testing\assertType; + +/** + * @template T + */ +class Repository +{ + /** + * @param array $items + */ + public function __construct(private array $items) {} + + /** + * @return ?T + */ + public function find(string $id) + { + return $this->items[$id] ?? null; + } +} + +/** + * @template T + */ +class Repository2 +{ + /** + * @param array $items + */ + public function __construct(private array $items) {} + + /** + * @return T|null + */ + public function find(string $id) + { + return $this->items[$id] ?? null; + } +} + +class Foo +{ + + /** + * @param Repository $r + * @return void + */ + public function doFoo(Repository $r): void + { + assertType('string|null', $r->find('foo')); + } + + /** + * @param Repository2 $r + * @return void + */ + public function doFoo2(Repository2 $r): void + { + assertType('string|null', $r->find('foo')); + } + +}