Fix phpstan/phpstan#6670: Return in finally does not always overwrite return in try-catch#5163
Conversation
|
Needs 4 more regression tests. |
1 similar comment
|
Needs 4 more regression tests. |
…n catch - Only emit FinallyExitPointsNode when the finally block always terminates, not just when it has any exit points - A return inside a catch within finally doesn't always execute, so it shouldn't be reported as unconditionally overwriting the try-catch return - New regression test in tests/PHPStan/Rules/Exceptions/data/bug-6670.php Closes phpstan/phpstan#6670
2d7d93d to
5bc1fec
Compare
ondrejmirtes
left a comment
There was a problem hiding this comment.
Please add regression tests for fixed issues based on https://github.com/phpstan/phpstan-src/actions/runs/22862533139 and add “closes X” to the PR description for them.
…change Closes phpstan/phpstan#12215 Closes phpstan/phpstan#11906 Closes phpstan/phpstan#7665 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Both background tasks have completed. As noted earlier, |
|
The review from VincentLanglet is an APPROVED review with no requested changes. There's nothing to address - the PR is already in good shape. Looking at the history:
The PR is ready for merge. No further action needed. |
staabm
left a comment
There was a problem hiding this comment.
I checked all tests are failling without the fix. lgtm.
|
The review from staabm is an APPROVED review with a positive comment ("I checked all tests are failling without the fix. lgtm."). There are no requested changes to address. The PR has now been approved by staabm and VincentLanglet (twice), with all previously requested changes (regression tests from ondrejmirtes) already addressed. No further action is needed. |
|
I processed this review but have nothing to report. |
Summary
PHPStan incorrectly reported "This return is overwritten by a different one in the finally block below" when the overwriting return was inside a
catchblock within thefinallyblock. Since thecatchonly executes if an exception is thrown, the return doesn't always overwrite the one in thetryblock.Changes
$finallyResult->isAlwaysTerminating()check insrc/Analyser/NodeScopeResolver.php(line ~2031) so theFinallyExitPointsNodeis only emitted when the finally block unconditionally terminates via an exit pointtests/PHPStan/Rules/Exceptions/data/bug-6670.phptestBug6670intests/PHPStan/Rules/Exceptions/OverwrittenExitPointByFinallyRuleTest.phpRoot cause
The condition for emitting
FinallyExitPointsNodeonly checkedcount($finallyResult->getExitPoints()) > 0, which is true whenever there's any exit point anywhere in the finally block — even inside acatch. But a return in acatchdoesn't always execute; it only runs when an exception is caught. The fix adds$finallyResult->isAlwaysTerminating()to ensure the warning is only shown when the finally block always terminates, meaning every code path through the finally hits an exit point.Test
The regression test reproduces the exact scenario from the issue: a
tryblock with a return, and afinallyblock containing atry/catchwhere only thecatchhas a return. The test expects no errors, since the finally block's return is conditional.Fixes phpstan/phpstan#6670
Closes phpstan/phpstan#12215
Closes phpstan/phpstan#11906
Closes phpstan/phpstan#7665