diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index ef55f3683f..4c04d00d94 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3776,6 +3776,11 @@ private function createConditionalExpressions( && !$guardHolder->getType()->isSuperTypeOf($theirExpressionTypes[$guardExprString]->getType())->no() ) || $guardHolder->getType()->isSuperTypeOf($theirExpressionTypes[$guardExprString]->getType())->yes() + || ( + !array_key_exists($exprString, $theirExpressionTypes) + && $holder->getType()->equals($guardHolder->getType()) + && !$guardHolder->getType()->isSuperTypeOf($theirExpressionTypes[$guardExprString]->getType())->no() + ) ) ) { continue; diff --git a/tests/PHPStan/Analyser/nsrt/bug-14469.php b/tests/PHPStan/Analyser/nsrt/bug-14469.php new file mode 100644 index 0000000000..e5bed8909f --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-14469.php @@ -0,0 +1,19 @@ +id === 10 ? 2 : null; + } elseif ($R['aa']) { + $aa = $R['aa']; + } + + if ($aa) { + assertType('mixed', $R['aa']); + } +} diff --git a/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php index fb5c504a94..8c6aec02bb 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php @@ -245,4 +245,10 @@ public function testBug12852(): void ]); } + public function testBug14469(): void + { + $this->treatPhpDocTypesAsCertain = true; + $this->analyse([__DIR__ . '/data/bug-14469.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-14469.php b/tests/PHPStan/Rules/Comparison/data/bug-14469.php new file mode 100644 index 0000000000..f7bb934c15 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-14469.php @@ -0,0 +1,88 @@ +id === 10 ? 2 : null; + } elseif ($R['aa']) { + $aa = $R['aa']; + } + + if ($aa) { + if (!$R['aa']) { + return []; + } + } + return $R; +} + +function testIfConstantCondition(array $R, bool $var1, object $user): void { + $aa = null; + + if ($var1) { + $aa = $user->id === 10 ? 2 : null; + } elseif ($R['aa']) { + $aa = $R['aa']; + } + + if ($aa) { + if ($R['aa']) { + // not always true + } + } +} + +function testFalseyBranch(array $R, bool $var1, object $user): void { + $bb = 'default'; + + if ($var1) { + $bb = $user->id === 10 ? null : 'active'; + } elseif (!$R['bb']) { + $bb = $R['bb']; + } + + if (!$bb) { + if ($R['bb']) { + return; + } + } +} + +function testWithElse(array $R, bool $var1, object $user): void { + $aa = null; + + if ($var1) { + $aa = $user->id === 10 ? 2 : null; + } elseif ($R['aa']) { + $aa = $R['aa']; + } else { + $aa = 0; + } + + if ($aa) { + if (!$R['aa']) { + return; + } + } +} + +function testMultipleElseif(array $R, bool $var1, bool $var2, object $user): void { + $aa = null; + + if ($var1) { + $aa = $user->id === 10 ? 2 : null; + } elseif ($var2) { + $aa = 42; + } elseif ($R['aa']) { + $aa = $R['aa']; + } + + if ($aa) { + if (!$R['aa']) { + return; + } + } +}