diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index a133b9fabc..5d98439a93 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -580,7 +580,7 @@ private static function intersectWithSubtractedType( Type $b, ): Type { - if ($a->getSubtractedType() === null) { + if ($a->getSubtractedType() === null || $b instanceof NeverType) { return $a; } @@ -621,7 +621,10 @@ private static function intersectWithSubtractedType( } elseif ($isBAlreadySubtracted->yes()) { $subtractedType = self::remove($a->getSubtractedType(), $b); - if ($subtractedType instanceof NeverType) { + if ( + $subtractedType instanceof NeverType + || !$subtractedType->isSuperTypeOf($b)->no() + ) { $subtractedType = null; } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index 3a0683d5ac..b6f79eeeeb 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -1100,6 +1100,18 @@ public function testBug10394(): void $this->analyse([__DIR__ . '/data/bug-10394.php'], []); } + public function testBug12930(): void + { + $this->treatPhpDocTypesAsCertain = true; + $this->analyse([__DIR__ . '/data/bug-12930.php'], []); + } + + public function testBug13628(): void + { + $this->treatPhpDocTypesAsCertain = true; + $this->analyse([__DIR__ . '/data/bug-13628.php'], []); + } + public function testBug9666(): void { $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; diff --git a/tests/PHPStan/Rules/Comparison/data/bug-12930.php b/tests/PHPStan/Rules/Comparison/data/bug-12930.php new file mode 100644 index 0000000000..54d614f931 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-12930.php @@ -0,0 +1,13 @@ +