Fix phpstan/phpstan#9349: Throw point are not properly recognized#5166
Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Open
Fix phpstan/phpstan#9349: Throw point are not properly recognized#5166phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
- When a method has @throws with a supertype of the caught exception (e.g. @throws RuntimeException with catch PDOException), implicit throw points from other method calls were incorrectly excluded from the catch scope - Phase 3 (implicit throw point matching) was skipped when explicit @throws matched even as "maybe", now it only skips when there's a definitive "yes" match - Added regression test in tests/PHPStan/Rules/Variables/data/bug-9349.php Closes phpstan/phpstan#9349
3984d04 to
b6073f0
Compare
VincentLanglet
approved these changes
Mar 15, 2026
Collaborator
Author
|
Already retrieved the results - all 11,578 tests passed. Nothing more to do. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a try block contains a method with
@throws RuntimeExceptionfollowed by other method calls (like$pdo->query()), and the catch block catchesPDOException(which extends RuntimeException), PHPStan incorrectly reported$sqlas "Undefined variable" instead of "Variable $sql might not be defined". This was because implicit throw points from other method calls were excluded from the catch scope.Changes
src/Analyser/NodeScopeResolver.php(Phase 3 of try-catch processing)$hasDirectExplicitNonThrowMatchflag that tracks whether any explicit@throwsannotation has a definitive (yes) type match with the catch typetests/PHPStan/Rules/Variables/data/bug-9349.phpand corresponding test method inDefinedVariableRuleTestRoot cause
The try-catch throw point matching has three phases: (1) Throwable catches all, (2) explicit @throws matching, (3) implicit throw point matching. Phase 3 was guarded by a condition that skipped it when explicit non-throw-expression matches existed (
!$onlyExplicitIsThrow). The problem was that@throws RuntimeExceptiononmaybeThrows()"maybe" matchedPDOException(since PDOException extends RuntimeException), causing Phase 3 to be skipped entirely. This excluded the implicit throw point from$pdo->query()(which executes after$sqlis assigned) from the catch scope.The fix adds tracking of whether the explicit match is definitive (the throw type IS a subtype of the catch type, i.e.
isSuperTypeOfreturnsyes) vs merely possible (maybe). Phase 3 is only skipped when there's a definitive explicit match, ensuring implicit throw points are included when the explicit@throwstype only partially overlaps with the catch type.Test
Added
tests/PHPStan/Rules/Variables/data/bug-9349.phpthat reproduces the original issue: a try block with$this->maybeThrows()(annotated@throws RuntimeException), then$sqlassignment, then$pdo->query($sql), caught byPDOException. The test verifies PHPStan reports "Variable $sql might not be defined" instead of "Undefined variable: $sql".Fixes phpstan/phpstan#9349