diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index b7ed0a624fb..18a7e5c81ac 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1653,7 +1653,7 @@ parameters: - rawMessage: 'Doing instanceof PHPStan\Type\NullType is error-prone and deprecated. Use Type::isNull() instead.' identifier: phpstanApi.instanceofType - count: 2 + count: 1 path: src/Type/TypeCombinator.php - diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 6ecc8dd8182..f3505786bdd 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -175,7 +175,7 @@ public static function containsNull(Type $type): bool { if ($type instanceof UnionType) { foreach ($type->getTypes() as $innerType) { - if ($innerType instanceof NullType) { + if ($innerType->isNull()->yes()) { return true; } } diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 35a12570069..e6d9639a749 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -1873,6 +1873,15 @@ public function testNullSafe(): void ]); } + public function testNullSafeOnTemplateTypeNarrowedAgainstNull(): void + { + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + + $this->analyse([__DIR__ . '/data/nullsafe-method-call-template-type.php'], []); + } + #[RequiresPhp('< 8.0.0')] public function testDisallowNamedArguments(): void { diff --git a/tests/PHPStan/Rules/Methods/data/nullsafe-method-call-template-type.php b/tests/PHPStan/Rules/Methods/data/nullsafe-method-call-template-type.php new file mode 100644 index 00000000000..b47b6aaa777 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/nullsafe-method-call-template-type.php @@ -0,0 +1,26 @@ += 8.0 + +namespace NullsafeMethodCallTemplateType; + +class Foo +{ + + public function getValue(): ?string + { + return null; + } + +} + +/** + * @template T + * @param T $foo + */ +function foo($foo) +{ + if ($foo !== null && !$foo instanceof Foo) { + throw new \Exception(); + } + + return $foo?->getValue(); +}