Skip to content

Let the compositional-key shortcut clear virtual-node keys on the invalidated side - #6154

Merged
ondrejmirtes merged 2 commits into
2.2.xfrom
invalidation-compositional-gates
Jul 30, 2026
Merged

Let the compositional-key shortcut clear virtual-node keys on the invalidated side#6154
ondrejmirtes merged 2 commits into
2.2.xfrom
invalidation-compositional-gates

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

Extracted from the resolve-type-rewrite-2 branch (its f65dfce), where the same change plus a caller-prefilter port cut its invalidation-check volume 5.7×.

The invalidation pre-filters treated every __phpstan occurrence in the invalidated expression's key as non-compositional: invalidating a virtual-keyed expression (a PossiblyImpureCallExpr entry, a foreach marker, …) disabled the substring shortcut and swept the scope's whole holder population through per-holder containment work. The holder side already consulted keyMayHideSubExpressions(); the invalidated side now does too. Three more printers join the compositional whitelist — ForeachValueByRef, IntertwinedVariableByReference, PropertyInitialization — with a comment documenting the soundness contract and why the foreach/parameter original-value markers can never be listed (they hide a synthesized Variable child on purpose; it is their invalidation hook).

Numbers on a src/Analyser src/Rules run: shouldInvalidateExpression() calls 759k → 433k, containment scans 629k → 297k. CPU is neutral within noise (12 interleaved pairs: −0.1%) — the surviving scans on 2.2.x are small ones — so the value is the structural reduction and convergence: the rewrite branch already carries this change, and landing it here removes those hunks from the eventual merge diff.

Mirrored in the native twin. Full test suite green with and without the active extension, make phpstan and make cs clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DaBZjgksga4c5s6Q9FniY7

ondrejmirtes and others added 2 commits July 30, 2026 19:56
…alidated side

The invalidation pre-filters treated every '__phpstan' occurrence in the
INVALIDATED expression's key as non-compositional: invalidating a
virtual-keyed expression disabled the substring shortcut and swept the
scope's whole holder population through the per-holder containment work.
The holder side already consulted keyMayHideSubExpressions(); the
invalidated side now does too, and ForeachValueByRef,
IntertwinedVariableByReference and PropertyInitialization join
COMPOSITIONAL_VIRTUAL_KEY_PREFIXES - their printers emit every walked
sub-node (or the node walks none). The foreach and parameter
original-value markers stay out deliberately: they hide a synthesized
Variable child that containment-based invalidation must keep finding
when the variable is reassigned.

src/Analyser+src/Rules run: shouldInvalidateExpression() calls
759k -> 433k, containment scans 629k -> 297k. Mirrored in the native
twin.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DaBZjgksga4c5s6Q9FniY7
@ondrejmirtes
ondrejmirtes merged commit 410436a into 2.2.x Jul 30, 2026
419 of 420 checks passed
@ondrejmirtes
ondrejmirtes deleted the invalidation-compositional-gates branch July 30, 2026 17:58
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