Problem
The three through-a-let unpacking families now disagree on where they look for the binder's uses. The record rules of #240 (propagateKnownObjectThroughLet, propagateObjectUpdateThroughLet) fold occurrences across the trailing sibling groupings of the same Let as well as its body — Let groupings scope sequentially, so a later binding's right-hand side legitimately reads an earlier binder. The constructor rule (propagateKnownCtorThroughLet, #214) and the array rule (propagateKnownArrayThroughLet, #225) instead decline outright when any sibling grouping references the binder:
, all ((== 0) . countFreeRefGrouping name) (before <> after)
For records the sibling reach was load-bearing (the defaults pattern let opts = {…}; chosen = opts { … } in … puts the update use in a sibling), but the same multi-binding shape exists for the other aggregates — e.g. a let-bound array consumed by a later sibling binding's length/element reads, or a constructor scrutinized by a sibling — and today those decline even though every use is a foldable eliminating read:
let xs = [10, 20]
total = xs !! 0 + xs !! 1 -- sibling grouping reads xs: rule declines
in f total total
Approach
Port the #240 mechanics to the two older rules: split with the shared findStandaloneBinding, take targets = body : (groupingExprs =<< after) (both helpers already live in Language.PureScript.Backend.IR.Optimizer), run the existing census over targets, fold with fmap (fmap (fmap foldReads)) after alongside the body, and keep declining on any before-grouping reference (impossible under globally-unique-counters scoping, but optimizedExpression also runs on generated input). The field/element-binders already take the consumed binding's position, so they scope over the trailing siblings unchanged.
Prerequisites / Relations
No open blockers. Builds on #240 (closed), which introduced the sibling-reach mechanics and the shared findStandaloneBinding/groupingExprs helpers; touches the rules introduced by #214 and #225 (both closed).
Verification
A unit spec per rule with the use in a trailing sibling grouping (mirroring the #240 spec "unpacks a literal used from a later sibling binding") goes from decline to fold; existing suites and goldens stay green, with any structural golden movement reviewed as legitimate extra folding.
Problem
The three through-a-
letunpacking families now disagree on where they look for the binder's uses. The record rules of #240 (propagateKnownObjectThroughLet,propagateObjectUpdateThroughLet) fold occurrences across the trailing sibling groupings of the sameLetas well as its body —Letgroupings scope sequentially, so a later binding's right-hand side legitimately reads an earlier binder. The constructor rule (propagateKnownCtorThroughLet, #214) and the array rule (propagateKnownArrayThroughLet, #225) instead decline outright when any sibling grouping references the binder:For records the sibling reach was load-bearing (the defaults pattern
let opts = {…}; chosen = opts { … } in …puts the update use in a sibling), but the same multi-binding shape exists for the other aggregates — e.g. alet-bound array consumed by a later sibling binding's length/element reads, or a constructor scrutinized by a sibling — and today those decline even though every use is a foldable eliminating read:Approach
Port the #240 mechanics to the two older rules: split with the shared
findStandaloneBinding, taketargets = body : (groupingExprs =<< after)(both helpers already live inLanguage.PureScript.Backend.IR.Optimizer), run the existing census overtargets, fold withfmap (fmap (fmap foldReads)) afteralongside the body, and keep declining on anybefore-grouping reference (impossible under globally-unique-counters scoping, butoptimizedExpressionalso runs on generated input). The field/element-binders already take the consumed binding's position, so they scope over the trailing siblings unchanged.Prerequisites / Relations
No open blockers. Builds on #240 (closed), which introduced the sibling-reach mechanics and the shared
findStandaloneBinding/groupingExprshelpers; touches the rules introduced by #214 and #225 (both closed).Verification
A unit spec per rule with the use in a trailing sibling grouping (mirroring the #240 spec "unpacks a literal used from a later sibling binding") goes from decline to fold; existing suites and goldens stay green, with any structural golden movement reviewed as legitimate extra folding.