diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 79b05cd0f8..ce853bd980 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1878,6 +1878,7 @@ public function processStmtNode( // explicit only $onlyExplicitIsThrow = true; + $hasDirectExplicitNonThrowMatch = false; if (count($matchingThrowPoints) === 0) { foreach ($throwPoints as $throwPointIndex => $throwPoint) { foreach ($catchTypes as $catchTypeIndex => $catchTypeItem) { @@ -1895,6 +1896,9 @@ public function processStmtNode( && !($throwNode instanceof Node\Stmt\Expression && $throwNode->expr instanceof Expr\Throw_) ) { $onlyExplicitIsThrow = false; + if ($catchTypeItem->isSuperTypeOf($throwPoint->getType())->yes()) { + $hasDirectExplicitNonThrowMatch = true; + } } $matchingThrowPoints[$throwPointIndex] = $throwPoint; } @@ -1902,7 +1906,7 @@ public function processStmtNode( } // implicit only - if (count($matchingThrowPoints) === 0 || $onlyExplicitIsThrow) { + if (count($matchingThrowPoints) === 0 || $onlyExplicitIsThrow || !$hasDirectExplicitNonThrowMatch) { foreach ($throwPoints as $throwPointIndex => $throwPoint) { if ($throwPoint->isExplicit()) { continue; diff --git a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php index add6c66beb..066817e7c5 100644 --- a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php +++ b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php @@ -1403,6 +1403,21 @@ public function testBug14019(): void $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-14019.php'], []); } + public function testBug9349(): void + { + $this->cliArgumentsVariablesRegistered = true; + $this->polluteScopeWithLoopInitialAssignments = false; + $this->checkMaybeUndefinedVariables = true; + $this->polluteScopeWithAlwaysIterableForeach = true; + + $this->analyse([__DIR__ . '/data/bug-9349.php'], [ + [ + 'Variable $sql might not be defined.', + 19, + ], + ]); + } + #[RequiresPhp('>= 8.0')] public function testBug14274(): void { diff --git a/tests/PHPStan/Rules/Variables/data/bug-9349.php b/tests/PHPStan/Rules/Variables/data/bug-9349.php new file mode 100644 index 0000000000..42c2fae5fa --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-9349.php @@ -0,0 +1,58 @@ +maybeThrows(); + $sql = "SELECT * FROM foo"; + $rs = $pdo->query($sql); + if ($result = $rs->fetch(\PDO::FETCH_ASSOC)) { + // do something + } + } catch (\PDOException $e) { + var_dump($sql); + } + } + + /** + * @throws \RuntimeException + */ + public function maybeThrows(): void + { + if (random_int(0, 1) === 1) { + throw new \RuntimeException(); + } + } + + public function test2(): void + { + global $pdo; + + try { + $this->maybeThrows2(); + $sql = "SELECT * FROM foo"; + $rs = $pdo->query($sql); + if ($result = $rs->fetch(\PDO::FETCH_ASSOC)) { + // do something + } + } catch (\PDOException $e) { + var_dump($sql); + } + } + + /** + * @throws \LogicException + */ + public function maybeThrows2(): void + { + if (random_int(0, 1) === 1) { + throw new \LogicException(); + } + } +}