Related to #142 but a distinct defect: the reference counts that isUsedOnce consults are computed from the original uberModuleBindings (captured by the closure), while the fold's accumulator already contains bindings with earlier substitutions applied. Exports are counted from the accumulated (fresh) versions, so the count mixes stale and fresh sources.
This cannot produce dangling references (substitution replaces all occurrences regardless of the count), but it can misjudge use-once: a large expression can get inlined into several sites (code bloat), or a legitimate inline can be skipped. idempotently partially self-corrects on later iterations, at the cost of extra passes.
Fix direction: compute counts against the same view of the module that the substitutions target; falls out naturally from the incremental-counting rework in #142.
Found during the 2026-07-02 backend audit.
Related to #142 but a distinct defect: the reference counts that
isUsedOnceconsults are computed from the originaluberModuleBindings(captured by the closure), while the fold's accumulator already contains bindings with earlier substitutions applied. Exports are counted from the accumulated (fresh) versions, so the count mixes stale and fresh sources.This cannot produce dangling references (substitution replaces all occurrences regardless of the count), but it can misjudge use-once: a large expression can get inlined into several sites (code bloat), or a legitimate inline can be skipped.
idempotentlypartially self-corrects on later iterations, at the cost of extra passes.Fix direction: compute counts against the same view of the module that the substitutions target; falls out naturally from the incremental-counting rework in #142.
Found during the 2026-07-02 backend audit.