Skip to content

[Performance] Hoist loop-invariant resolve+continue guards above foreach - #8761

Merged
TomasVotruba merged 1 commit into
mainfrom
fix-invariant-continue-in-foreach
Oct 22, 2026
Merged

TomasVotruba merged 1 commit into
mainfrom
fix-invariant-continue-in-foreach

Conversation

@TomasVotruba

Copy link
Copy Markdown
Member

Two rules resolved a value from a loop-invariant node inside a foreach, then guarded it with a continue. Since the node does not change per iteration, the resolve returns the same value every pass and the guard fires identically - so it belongs above the loop, bailing once.

StaticCallToNewRector - $class = $this->getName($node->class) + null continue depended only on $node->class; hoisted above the loop with a single return null.

AddArrowFunctionParamArrayWhereDimFetchRector - $this->getType($closureItems) and its object-array guard were run per closure param, though $closureItems is fixed for the whole param loop; resolved once before the loop.

Found by an AST scan for the pattern: inside a foreach, an assignment from a method call whose arguments and receiver are all loop-invariant, immediately followed by if (...) { continue; } testing the assigned variable.

In StaticCallToNewRector and AddArrowFunctionParamArrayWhereDimFetchRector a value resolved from a loop-invariant node was fetched inside a foreach, then a continue guard repeated it every iteration. Hoist the resolve above the loop and bail once.
@TomasVotruba
TomasVotruba merged commit c40ecff into main Oct 22, 2026
48 of 49 checks passed
@TomasVotruba
TomasVotruba deleted the fix-invariant-continue-in-foreach branch October 22, 2026 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant