diff --git a/src/Analyser/StatementsHandler.php b/src/Analyser/StatementsHandler.php index c306b69bc72..95ce2d528ae 100644 --- a/src/Analyser/StatementsHandler.php +++ b/src/Analyser/StatementsHandler.php @@ -794,7 +794,9 @@ public function getOverridingThrowPoints(Node\Stmt $statement, MutatingScope $sc return []; } - return [InternalThrowPoint::createExplicit($scope, $throwsType, $statement, false)]; + $fromThrowExpr = $statement instanceof Node\Stmt\Expression && $statement->expr instanceof Expr\Throw_; + + return [InternalThrowPoint::createExplicit($scope, $throwsType, $statement, false, $fromThrowExpr)]; } } diff --git a/src/Analyser/StmtHandler/TryCatchHandler.php b/src/Analyser/StmtHandler/TryCatchHandler.php index aedccaccac8..38215176829 100644 --- a/src/Analyser/StmtHandler/TryCatchHandler.php +++ b/src/Analyser/StmtHandler/TryCatchHandler.php @@ -142,11 +142,7 @@ public function processStmt( if (!$throwPoint->isExplicit()) { continue; } - $throwNode = $throwPoint->getNode(); - if ( - !$throwNode instanceof Expr\Throw_ - && !($throwNode instanceof Node\Stmt\Expression && $throwNode->expr instanceof Expr\Throw_) - ) { + if (!$throwPoint->isFromThrowExpr()) { $onlyExplicitIsThrow = false; } diff --git a/tests/PHPStan/Analyser/nsrt/bug-14990.php b/tests/PHPStan/Analyser/nsrt/bug-14990.php new file mode 100644 index 00000000000..ae541f0c8fe --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-14990.php @@ -0,0 +1,57 @@ + throw new \InvalidArgumentException(), [1, 2]); + } catch (\InvalidArgumentException $e) { + assertVariableCertainty(TrinaryLogic::createMaybe(), $a); + } + } + + public function doThrowInClosureArg(): void + { + try { + doFoo(); + $a = 1; + array_map(static function (int $i): int { + throw new \InvalidArgumentException(); + }, [1, 2]); + } catch (\InvalidArgumentException $e) { + assertVariableCertainty(TrinaryLogic::createMaybe(), $a); + } + } + + public function doThrowInCalledClosure(): void + { + $callback = static function (): void { + throw new \InvalidArgumentException(); + }; + try { + doFoo(); + $a = 1; + $callback(); + } catch (\InvalidArgumentException $e) { + assertVariableCertainty(TrinaryLogic::createMaybe(), $a); + } + } + + public function doThrowInImmediatelyInvokedClosure(): void + { + try { + doFoo(); + $a = 1; + (static function (): void { + throw new \InvalidArgumentException(); + })(); + } catch (\InvalidArgumentException $e) { + assertVariableCertainty(TrinaryLogic::createMaybe(), $a); + } + } + + public function doThrowInClosureVariablePassedAsCallable(): void + { + $callback = static function (int $i): int { + throw new \InvalidArgumentException(); + }; + try { + doFoo(); + $a = 1; + array_map($callback, [1, 2]); + } catch (\InvalidArgumentException $e) { + assertVariableCertainty(TrinaryLogic::createMaybe(), $a); + } + } + + public function doAnnotatedThrowStatement(): void + { + try { + doFoo(); + $a = 1; + /** @throws \InvalidArgumentException */ + throw new \InvalidArgumentException(); + } catch (\InvalidArgumentException $e) { + assertVariableCertainty(TrinaryLogic::createMaybe(), $a); + } + } + + public function doDocumentedThrowInClosureArg(): void + { + try { + doFoo(); + $a = 1; + array_map(function (int $i): int { + $this->throwInvalidArgument(); + + return $i; + }, [1, 2]); + } catch (\InvalidArgumentException $e) { + assertVariableCertainty(TrinaryLogic::createYes(), $a); + } + } + /** * @throws \InvalidArgumentException */ diff --git a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php index debc27ee4e3..e9be1f1aaed 100644 --- a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php @@ -1264,6 +1264,11 @@ public function testBug14966(): void $this->analyse([__DIR__ . '/data/bug-14966.php'], []); } + public function testBug14990(): void + { + $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-14990.php'], []); + } + public function testBug14847(): void { $this->analyse([__DIR__ . '/data/bug-14847.php'], [