Skip to content

Process unrolled foreach iteration body in original context#5559

Merged
ondrejmirtes merged 2 commits into2.1.xfrom
fix-unrolled-foreach-nested-loop-context
Apr 28, 2026
Merged

Process unrolled foreach iteration body in original context#5559
ondrejmirtes merged 2 commits into2.1.xfrom
fix-unrolled-foreach-nested-loop-context

Conversation

@ondrejmirtes
Copy link
Copy Markdown
Member

@ondrejmirtes ondrejmirtes commented Apr 28, 2026

Summary

  • The unrolled-constant-array foreach path was processing each iteration's body with $context->enterDeep(), which suppresses LOOP_SCOPE_ITERATIONS stabilization in nested loops. Because unrolling visits each element exactly once (no outer iteration to converge accumulators), nested loops inside the body produced single-element constant arrays instead of stabilized list/non-empty-list types.
  • Fixed by passing the original $context to processStmtNodesInternal, so nested loops inside an unrolled iteration's body can stabilize on their own (the non-unrolled path still uses enterDeep because the outer 3-iteration loop is what makes accumulators converge there).
  • Added regression tests bug-14543.php and bug-9332.php for the reported cases.
  • Updated bug-14489.php expectation to the more precise array{array{1}, array{4}} since the inner foreach over a fully-known constant array now also unrolls and produces precise sequential types (verified to match runtime output via php -r).

Test plan

  • vendor/bin/phpunit tests/PHPStan/Analyser/NodeScopeResolverTest.php — 1557 tests, 0 failures
  • New regression tests pass with the fix and fail without it
  • Manual reproduction from the bug reports now reports the precise types

Closes phpstan/phpstan#9332
Closes phpstan/phpstan#14543

🤖 Generated with Claude Code

ondrejmirtes and others added 2 commits April 28, 2026 18:29
…sted loops stabilize

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes phpstan/phpstan#9332

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ondrejmirtes ondrejmirtes merged commit 2f825fc into 2.1.x Apr 28, 2026
354 of 356 checks passed
@ondrejmirtes ondrejmirtes deleted the fix-unrolled-foreach-nested-loop-context branch April 28, 2026 16:36
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.

1 participant