Skip to content

Report loop variable overwrites only for variables still in use - #333

Merged
ondrejmirtes merged 1 commit into
2.1.xfrom
loop-variable-reuse
Sep 11, 2026
Merged

ondrejmirtes merged 1 commit into
2.1.xfrom
loop-variable-reuse

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

Closes #332, fixes phpstan/phpstan#9940. Requires phpstan/phpstan-src#6414 (merged, in the current 2.3.x dev phar).

OverwriteVariablesWithForeachRule and OverwriteVariablesWithForLoopInitRule now listen on VariableWritesNode and report a foreach key/value binding or a for-loop initial assignment only when getVariableOverwritingLoop() returns the loop: the variable was assigned before the loop and is read after it, with no assignment in between other than the loop's own bindings and updates. Reusing a spent loop variable is silent, including the flag-then-check pattern from #332 and the #9940 reproducer.

Behaviour changes beyond the issue:

  • A conditionally assigned variable before the loop (if ($c) { $x = 1; }) now reports when $x is read after the loop; it was Maybe and silent before. The old value genuinely survives an empty loop there.
  • Top-level script code is no longer checked, since VariableWritesNode is emitted per function-like, same as phpstan-src's dead-code rules.
  • The for-loop rule reports for ($i = 0; ...) over an existing $i only when $i is read after the loop.

Existing fixtures keep every original error (reads were added after the loops); new fixtures show the silent cases and the positive contrasts (nested loop clobbering an outer loop variable, read in a later iteration of an outer loop, list targets).

The static analysis job needs phpstan/phpstan-src#6415 (@api on the two classes) in the dev phar; tests and coding standards pass with the current one.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LYiPGg9cpsKLyK6X5BrJTT

Foreach key/value and for-loop init overwrites are reported only when
the loop takes over a variable assigned before it and read after it,
as answered by VariableWritesNode::getVariableOverwritingLoop().
Reusing a spent loop variable no longer reports.

Closes #332

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LYiPGg9cpsKLyK6X5BrJTT
@ondrejmirtes
ondrejmirtes merged commit 4908484 into 2.1.x Sep 11, 2026
17 of 45 checks passed
@ondrejmirtes
ondrejmirtes deleted the loop-variable-reuse branch September 11, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant