diff --git a/src/Reflection/Php/PhpParameterFromParserNodeReflection.php b/src/Reflection/Php/PhpParameterFromParserNodeReflection.php index 6970ac1c70..09c17d2a46 100644 --- a/src/Reflection/Php/PhpParameterFromParserNodeReflection.php +++ b/src/Reflection/Php/PhpParameterFromParserNodeReflection.php @@ -62,7 +62,10 @@ public function getType(): Type $phpDocType = $this->phpDocType; if ($phpDocType !== null && $this->defaultValue !== null) { if ($this->defaultValue instanceof NullType) { - $phpDocType = \PHPStan\Type\TypeCombinator::addNull($phpDocType); + $inferred = $phpDocType->inferTemplateTypes($this->defaultValue); + if ($inferred->isEmpty()) { + $phpDocType = \PHPStan\Type\TypeCombinator::addNull($phpDocType); + } } } $this->type = TypehintHelper::decideType($this->realType, $phpDocType); diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 8a1737acee..ad23367c6d 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -403,6 +403,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2413.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3446.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/getopt.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/generics-default.php'); } /** diff --git a/tests/PHPStan/Analyser/data/generics-default.php b/tests/PHPStan/Analyser/data/generics-default.php new file mode 100644 index 0000000000..7bf2d3dff5 --- /dev/null +++ b/tests/PHPStan/Analyser/data/generics-default.php @@ -0,0 +1,44 @@ +doFoo()); + assertType('1', $this->doFoo(1)); + } + + /** + * @template T + * @param T $default + */ + public function doBaz($default = null): void + { + assertType('T (method GenericsDefault\Foo::doBaz(), argument)', $default); + } + + /** + * @template T + * @param T|null $default + */ + public function doLorem($default = null): void + { + assertType('T (method GenericsDefault\Foo::doLorem(), argument)|null', $default); + } + +} diff --git a/tests/PHPStan/Rules/Methods/IncompatibleDefaultParameterTypeRuleTest.php b/tests/PHPStan/Rules/Methods/IncompatibleDefaultParameterTypeRuleTest.php index 4999bce4d2..cf9640685c 100644 --- a/tests/PHPStan/Rules/Methods/IncompatibleDefaultParameterTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/IncompatibleDefaultParameterTypeRuleTest.php @@ -40,4 +40,9 @@ public function testBug4011(): void $this->analyse([__DIR__ . '/data/bug-4011.php'], []); } + public function testBug2573(): void + { + $this->analyse([__DIR__ . '/data/bug-2573.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index 69e4c8efe2..d02eb19813 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -490,4 +490,17 @@ public function testBug4803(): void $this->analyse([__DIR__ . '/../../Analyser/data/bug-4803.php'], []); } + public function testBug2573(): void + { + $this->analyse([__DIR__ . '/data/bug-2573-return.php'], []); + } + + public function testBug4603(): void + { + if (PHP_VERSION_ID < 80000 && !self::$useStaticReflectionProvider) { + $this->markTestSkipped('Test requires PHP 8.0'); + } + $this->analyse([__DIR__ . '/data/bug-4603.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-2573-return.php b/tests/PHPStan/Rules/Methods/data/bug-2573-return.php new file mode 100644 index 0000000000..6b447194e2 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-2573-return.php @@ -0,0 +1,32 @@ + $array + * @param array-key $key + * @param D $default + * @return V|D + */ + function idx($array, $key, $default = null) { + if (array_key_exists($key, $array)) { + return $array[$key]; + } + return $default; + } + + /** + * @param array $arr + * @return int + */ + function example($arr) { + return $this->idx($arr, 5, 42); + } + +} diff --git a/tests/PHPStan/Rules/Methods/data/bug-2573.php b/tests/PHPStan/Rules/Methods/data/bug-2573.php new file mode 100644 index 0000000000..5d9755fa02 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-2573.php @@ -0,0 +1,19 @@ += 8.0 + +namespace Bug4603; + +class Foo +{ + + /** + * @param T $val + * + * @return T + * + * @template T + */ + function fcn(mixed $val = null) + { + return $val; + } + +}