Found during round-7 review of #2612 (issue-2088's implementation plan).
Problem
docs/plans/issue-2088.md's escape-analysis design now recurses into a for...of loop variable's own references exactly as it already recurses into a rebinding alias (round 4's fix, applied to the for_in_statement branch by round 7) — but only when the loop variable is a single plain identifier, mirroring the exact extraction collectForOfBinding (src/extractors/javascript.ts:4280, and its Rust mirror collect_for_of_binding at crates/codegraph-core/src/extractors/javascript.rs:7553) already performs. A DESTRUCTURING loop variable is different in kind, not just untracked:
const B = [{ matches: isBar }];
for (const { matches } of B) matches(x);
collectForOfBinding requires the declarator's name field to be a plain identifier (verified: it looks for a variable_declarator child and only records varName when nc?.type === 'identifier'), so a destructuring left never produces a forOfBindings entry at all — the solver has no points-to fact for matches here, and collectInvokedPropertySites cannot correlate matches(x) to B's site regardless of how B itself is referenced. Round 7 excludes this shape from the tracked set entirely (the array reference is untracked when its for-of loop variable is not a single plain identifier), which is the array-element analogue of #2620's bare-property-read gap — the array is iterated and a property is extracted per-element, rather than read once off a single object, but the missing alias-tracking is the same shape of gap.
Impact
Recall-only, same direction as #2620: matches(x) is a real invocation of isBar, but no existing channel can prove it. The site correctly falls back to T2.
Fix sketch
Would need a new solver channel that, for a destructuring for-of over an array of object literals, seeds a points-to-like fact per destructured property name back to the site — worth designing alongside #2620's own fix (property-value aliasing), since both are instances of "a property is extracted from a tracked binding into a NEW alias this design does not yet follow."
Not attempted in #2612 — that PR is a docs-only plan revision.
Found during round-7 review of #2612 (issue-2088's implementation plan).
Problem
docs/plans/issue-2088.md's escape-analysis design now recurses into afor...ofloop variable's own references exactly as it already recurses into a rebinding alias (round 4's fix, applied to thefor_in_statementbranch by round 7) — but only when the loop variable is a single plain identifier, mirroring the exact extractioncollectForOfBinding(src/extractors/javascript.ts:4280, and its Rust mirrorcollect_for_of_bindingatcrates/codegraph-core/src/extractors/javascript.rs:7553) already performs. A DESTRUCTURING loop variable is different in kind, not just untracked:collectForOfBindingrequires the declarator'snamefield to be a plainidentifier(verified: it looks for avariable_declaratorchild and only recordsvarNamewhennc?.type === 'identifier'), so a destructuringleftnever produces aforOfBindingsentry at all — the solver has no points-to fact formatcheshere, andcollectInvokedPropertySitescannot correlatematches(x)toB's site regardless of howBitself is referenced. Round 7 excludes this shape from the tracked set entirely (the array reference is untracked when its for-of loop variable is not a single plain identifier), which is the array-element analogue of #2620's bare-property-read gap — the array is iterated and a property is extracted per-element, rather than read once off a single object, but the missing alias-tracking is the same shape of gap.Impact
Recall-only, same direction as #2620:
matches(x)is a real invocation ofisBar, but no existing channel can prove it. The site correctly falls back to T2.Fix sketch
Would need a new solver channel that, for a destructuring for-of over an array of object literals, seeds a points-to-like fact per destructured property name back to the site — worth designing alongside #2620's own fix (property-value aliasing), since both are instances of "a property is extracted from a tracked binding into a NEW alias this design does not yet follow."
Not attempted in #2612 — that PR is a docs-only plan revision.