You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Forward-captured const stays TDZ-poisoned after initialization (mutual recursion; error also names 'undefined' not the binding) #9721
A forward reference between two mutually recursive const arrows throws ReferenceError: Cannot access undefined before initialization at call time, long after both bindings are initialized. Deterministic, 5/5 runs. Not a regression — it reproduces identically on 28c292517 and on that commit plus #9720.
node 26.5.1 : fact=120 / off=off-called / sub2=unsubbed / multi=b/a / fib=55 / even10=true odd7=true
perry : fact=120 / off=off-called / sub2=unsubbed / multi=b/a / fib=55
ReferenceError: Cannot access undefined before initialization
at even (<anonymous>)
at main (<anonymous>)
even(10) runs after both even and odd have been initialized, so there is no TDZ window — node returns true. Perry reads odd's forward-declared box and still finds the TDZ sentinel there.
Two defects, one line
The TDZ sentinel is not cleared (or the wrong slot is read) for a forward-captured let/const under this combination, so a legal post-initialization read throws.
The message names undefined instead of the binding. Node says Cannot access 'odd' before initialization. Whatever formats this message is not getting the name, which makes every instance of this error hard to attribute — worth fixing independently of (1).
What it takes to trigger
Deleting the const off = ev.on(() => off()) line makes it pass, so a binding whose own initializer closes over it is necessary. It is not sufficient: off plus the mutual pair alone passes, and so does off plus any single one of fact / fib / the multi-declarator / sub2 plus the pair. The failure needs the fuller combination above — likely a capacity or ordering effect in the per-scope forward-registration bookkeeping (pre_register_forward_captured_lets / lexical_forward_decls / tdz_forward_ids in crates/perry-hir/src/lower_decl/block.rs) rather than any one shape.
Found while validating #9720 (which is a different bug in the same pre-pass — that one is a missing registration, this one is a registration whose sentinel outlives initialization). #9720 neither causes nor fixes this; both arms of its A/B fail identically here.
Fixed by #9762, landed on main via merge train #9804. The train merged as its own branch, so the close-keyword in #9762 never fired — closing manually. Verified the fix is on main by patch-id (git cherry), not just by the PR being closed.
Activity
proggeramlug commentedon Sep 5, 2026
Fixed by #9762, landed on
mainvia merge train #9804. The train merged as its own branch, so the close-keyword in #9762 never fired — closing manually. Verified the fix is onmainby patch-id (git cherry), not just by the PR being closed.