Skip to content

Fix phpstan/phpstan#14328: Unreachable statement information gets lost#5253

Open
phpstan-bot wants to merge 6 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-8h4reyh
Open

Fix phpstan/phpstan#14328: Unreachable statement information gets lost#5253
phpstan-bot wants to merge 6 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-8h4reyh

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

When a never-returning function call was used as an argument in a chained method call (e.g. new Foo()->returnThis($callback())->returnThis('x')), PHPStan failed to report the next statement as unreachable.

Changes

  • Fixed src/Analyser/ExprHandler/MethodCallHandler.php:139 — changed $isAlwaysTerminating = ... to $isAlwaysTerminating = $isAlwaysTerminating || (...) to preserve the terminating status from the var expression
  • Fixed src/Analyser/ExprHandler/StaticCallHandler.php:195 — same fix for static method calls
  • Added regression test in tests/PHPStan/Rules/DeadCode/data/bug-14328.php

Root cause

In MethodCallHandler and StaticCallHandler, when checking whether the method's return type is never, the code overwrote $isAlwaysTerminating instead of OR-ing it with the existing value. This meant that if a previous part of the expression (such as a never-returning argument in an inner chained call) had already set $isAlwaysTerminating = true, it was reset to false by the outer method call's return type check.

FuncCallHandler already used the correct || pattern at the equivalent line.

Test

Added tests/PHPStan/Rules/DeadCode/data/bug-14328.php which reproduces the exact scenario from the issue: a never-returning callback passed as argument in a chained method call, with the next line expected to be reported as unreachable.

Fixes phpstan/phpstan#14328

- MethodCallHandler and StaticCallHandler overwrote $isAlwaysTerminating
  instead of OR-ing with the existing value when checking the return type
- This caused never-returning arguments in chained calls to not propagate
  the always-terminating status to the outer call
- Added regression test for phpstan/phpstan#14328

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the syntax (new Foo()) to solve lint issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@phpstan-bot
Copy link
Collaborator Author

Already retrieved this output earlier — all 11609 tests passed. Everything is done and pushed.

@VincentLanglet VincentLanglet requested a review from staabm March 19, 2026 20:49
@phpstan-bot
Copy link
Collaborator Author

The review from VincentLanglet is an APPROVED state with no new change requests. The previous comment about wrapping new Foo() in parentheses was already addressed in commit 87a004778.

There are no outstanding changes to make — the PR is approved and ready to merge.

Copy link
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a similar test for static method

…ning arg

Addresses review feedback from staabm: the StaticCallHandler fix was
missing a test. Restructured the test data into separate functions so
each scenario (method call chain vs static call) is independently tested.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@phpstan-bot
Copy link
Collaborator Author

Already retrieved — all 11609 tests passed. Everything is done and pushed.

phpstan-bot and others added 2 commits March 19, 2026 21:26
Add a test case where a static call with a never-returning argument
is chained to a method call, testing the interaction between
StaticCallHandler and MethodCallHandler isAlwaysTerminating propagation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous tests covered static calls chained with instance method
calls (->), but not static calls chained with other static calls (::).
This new test exercises the StaticCallHandler fix where the class
expression is itself a static call with a never-returning argument.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@phpstan-bot
Copy link
Collaborator Author

All done. All four background tasks (two test suite runs and two PHPStan analyses) completed successfully, and the commit is pushed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants