Skip to content

Add regression test for @var annotation before foreach not defining the expression variable#5458

Merged
VincentLanglet merged 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-7hl0yka
Apr 14, 2026
Merged

Add regression test for @var annotation before foreach not defining the expression variable#5458
VincentLanglet merged 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-7hl0yka

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

Issue phpstan/phpstan#6688 reported a false positive "Variable $result might not be defined" when a @var PHPDoc annotation was placed before a foreach loop to define the expression variable. This was fixed in commit 4a08845 but no regression test was added. This PR adds the regression test.

Changes

  • Added test data file tests/PHPStan/Rules/Variables/data/bug-6688.php reproducing both the original issue and the maintainer's confirmation case
  • Added testBug6688() method in tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php

Root cause

The Foreach_ statement was explicitly excluded from the general processStmtVarAnnotation call at the top of NodeScopeResolver::processStmtNode() (line 507). This exclusion exists because foreach has its own @var annotation handling for iteration variables via enterForeach(). However, the processVarAnnotation call for the foreach expression variable was positioned AFTER processExprNode, meaning the variable was evaluated before the @var annotation could define it. The fix (commit 4a08845) moved this call to before the expression processing.

Other control flow statements (if, while, do-while, for, switch, match) are NOT affected because they are handled by the general processStmtVarAnnotation call which is not excluded for them.

Test

The regression test verifies that:

  • /** @var string[] $c */ foreach ($c as $v) produces no "variable undefined" error (the @var annotation defines $c)
  • /** @var string[][] $result */ foreach ($result as $data) produces no error (the original issue)
  • An unannotated variable (echo $a) still correctly reports "Variable $a might not be defined"

Confirmed the test fails when the fix is reverted (removing lines 1222-1224 in NodeScopeResolver.php).

Fixes phpstan/phpstan#6688

…ng the expression variable

- Add regression test for phpstan/phpstan#6688 verifying that `@var` PHPDoc
  annotations before `foreach` correctly define the expression variable in scope
- Test covers the original issue: `/** @var string[][] $result */ foreach ($result as $data)`
  and the maintainer's reproduction: `/** @var string[] $c */ foreach ($c as $v)`
- The fix was applied in commit 4a08845 by moving the `processVarAnnotation`
  call before `processExprNode` in the `Foreach_` branch of `NodeScopeResolver`
- Investigated analogous constructs (if, while, do-while, for, switch, match):
  all are correctly handled by the general `processStmtVarAnnotation` call at
  the top of `processStmtNode` — only `Foreach_` was excluded from that general
  handling and needed its own pre-expression annotation processing
@VincentLanglet VincentLanglet requested a review from staabm April 14, 2026 07:53
@VincentLanglet VincentLanglet merged commit 04a99c1 into phpstan:2.1.x Apr 14, 2026
383 checks passed
@VincentLanglet VincentLanglet deleted the create-pull-request/patch-7hl0yka branch April 14, 2026 08:10
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.

4 participants