Skip to content

Narrow the foreach source offset when the value variable is narrowed - #6386

Open
ondrejmirtes wants to merge 2 commits into
2.3.xfrom
dependent-types-foreach-alias
Open

ondrejmirtes wants to merge 2 commits into
2.3.xfrom
dependent-types-foreach-alias

Conversation

@ondrejmirtes

@ondrejmirtes ondrejmirtes commented Sep 5, 2026 •

Copy link
Copy Markdown
Member

Inside foreach ($data as $key => $value), narrowing the value variable now also narrows the aliased source element $data[$key] for the current iteration, because they are two names for one runtime value.

The alias is a pure precision optimisation, so it is dropped conservatively whenever a write could desync it from the value variable — writes that bypass the assignment path (by-reference closure use, extract(), dynamic-variable writes), cross-iteration writes into the iteratee, and any write whose target cannot be proven to be exactly the current key. The same-key sub-offset write is kept.

Two follow-up commits close the soundness holes found during review; the file is not shadowed by the turbo extension. Regression tests cover the fix and the bypass shapes; the full NodeScopeResolverTest stays green and a local issue-bot run confirms the fix plus one collateral fix (#12500) with no regressions.

Closes phpstan/phpstan#7508
Closes phpstan/phpstan#12500

🤖 Generated with Claude Code

@phpstan-bot

Copy link
Copy Markdown
Collaborator

You've opened the pull request against the latest branch 2.3.x. PHPStan 2.3 is not going to be released for months. If your code is relevant on 2.2.x and you want it to be released sooner, please rebase your pull request and change its target to 2.2.x.

ondrejmirtes and others added 2 commits October 31, 2026 14:20
…ratee dim fetch

Inside foreach ($array as $key => $value), the value variable and
$array[$key] hold the same runtime value until any of $value, $key or the
iteratee is written. enterForeach() now records that alias
(ForeachValueAliasExpr, invalidated through containment of all three
participating expressions), and applySpecifiedTypes() intersects a
narrowing landed on the value variable into the tracked dim fetch holder
while the link is intact.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGhnJQpUWRRpg6H5LuWJkA
Amp-Thread-ID: https://ampcode.com/threads/T-01a19219-874b-7614-bea5-a5f416095107
@ondrejmirtes
ondrejmirtes force-pushed the dependent-types-foreach-alias branch from 405eec0 to faf0b8c Compare October 31, 2026 14:20
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.

Narrowing array type after foreach loop Array value type is not narrowed when value itself is checked

2 participants