diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index a43ba35dda..87276600a9 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -840,6 +840,20 @@ private function isGlobalVariable(string $variableName): bool return in_array($variableName, self::SUPERGLOBAL_VARIABLES, true); } + private function exprContainsSuperGlobal(Expr $expr): bool + { + $containsSuperGlobal = $expr->getAttribute(self::CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME); + if ($containsSuperGlobal !== null) { + return $containsSuperGlobal; + } + + $nodeFinder = new NodeFinder(); + $containsSuperGlobal = $nodeFinder->findFirst($expr, fn (Node $node) => $node instanceof Variable && is_string($node->name) && $this->isGlobalVariable($node->name)) !== null; + $expr->setAttribute(self::CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME, $containsSuperGlobal); + + return $containsSuperGlobal; + } + /** @api */ public function hasConstant(Name $name): bool { @@ -3603,9 +3617,13 @@ private function createConditionalExpressions( } foreach ($variableTypeGuards as $guardExprString => $guardHolder) { + $exprExistsInTheirs = array_key_exists($exprString, $theirExpressionTypes) + && $theirExpressionTypes[$exprString]->getCertainty()->yes(); + if (!$exprExistsInTheirs) { + $exprExistsInTheirs = $this->exprContainsSuperGlobal($holder->getExpr()); + } if ( - array_key_exists($exprString, $theirExpressionTypes) - && $theirExpressionTypes[$exprString]->getCertainty()->yes() + $exprExistsInTheirs && array_key_exists($guardExprString, $theirExpressionTypes) && $theirExpressionTypes[$guardExprString]->getCertainty()->yes() && !$guardHolder->getType()->isSuperTypeOf($theirExpressionTypes[$guardExprString]->getType())->no() diff --git a/tests/PHPStan/Rules/Variables/IssetRuleTest.php b/tests/PHPStan/Rules/Variables/IssetRuleTest.php index fd841e49b1..0f57cd0fd3 100644 --- a/tests/PHPStan/Rules/Variables/IssetRuleTest.php +++ b/tests/PHPStan/Rules/Variables/IssetRuleTest.php @@ -562,4 +562,11 @@ public function testBug14393(): void ]); } + public function testBug14421(): void + { + $this->treatPhpDocTypesAsCertain = true; + + $this->analyse([__DIR__ . '/data/bug-14421.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Variables/data/bug-14421.php b/tests/PHPStan/Rules/Variables/data/bug-14421.php new file mode 100644 index 0000000000..eafdc7068a --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-14421.php @@ -0,0 +1,20 @@ +