Repository navigation
fix(hir): closes #461 — pre-register local for const f = (arrow) decls so nested closures resolve self-references (v0.5.600) - #524
Merged
Conversation
…cls so nested closures resolve self-references (v0.5.600)
A `const f = (...) => ...` arrow declaration inside a function body was
not pre-registered as a local before its initializer was lowered, so any
nested closure inside that initializer that referenced `f` couldn't find
it via `lookup_local` and fell through to `lookup_imported_func`. When a
namespace import shared the same name (Effect's `import * as pull from
"./stream/pull.js"` + `const pull = (state) => { ... pull(...) ... }`),
the inner reference lowered to `ExternFuncRef { name: "pull" }` and
codegen's "Native library functions" fallback emitted a direct LLVM call
to the bare symbol `@pull`, surfacing as `_pull` undefined at link time.
Function declarations already pre-register their local id before lowering
the body. This commit applies the same treatment to `const f = arrow` /
`const f = function() {}` initializers in `lower_var_decl_with_destructuring`'s
`Pat::Ident` arm. Gated on function-expr init only, so `const x = x + 1`
keeps its (correct) TDZ-violation behavior.
Parity sweep: 209 pass / 3 known fails / 1 known compile-fail / 13
skipped — no regressions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_pull+ class-as-function references (Union/Emit/Order) #461 (bare_pullsymbol — last residual link error from the Effect repro after perry-codegen:export { local as keyword }re-exports don't emit definitions for contextual-keyword names (void/async/await/try/delete/continue) #460/DX: unify R005 / #463 message format across all unimplemented-API rejection paths (perry/ui, perry/media, perry/plugin, perry/updater) #525 closed Order/Union/Emit).const f = (arrow)/const f = function() {}locals inlower_var_decl_with_destructuringBEFORE lowering the init, mirroring whatfunction f() {}decls already do — so self-recursive references inside the closure body resolve vialookup_localinstead of falling through tolookup_imported_funcand emitting a bare symbol at link time.const x = x + 1keeps its (correct) TDZ-violation semantics.Root cause
Effect's
internal/stream.tshas both:import * as pull from "./stream/pull.js"(namespace import at module top)const pull = (state, ...) => { … pull(...) … }(local rebinding inside three exported functions)Without pre-registration, the inner closures'
pull(...)reference sawlookup_local("pull") == None→lookup_imported_func("pull") == Some("pull")→ HIR lowered asExpr::ExternFuncRef { name: "pull" }→lower_call.rs::ExternFuncRef's "Native library functions" fallback emittedcall double @pull(...)→ linker:Undefined symbol: _pull.Test plan
import * as pull+const pullrebind): returns101 / 101matching Node (was:_pullundefined at link)const fac = (n) => n < 2 ? 1 : n * fac(n-1)returns 120 / 3628800const fib = function(n) { ... }returns 55bun add effect && perry compile test_minimal.ts:_pullno longer appears in undefined symbols (remaining errors are unrelated cross-module references —_perry_fn_…_{Cron,Duration,Graph}_ts__*— separate issue, not blocking perry-codegen: residual link errors on Effect — bare_pull+ class-as-function references (Union/Emit/Order) #461)test_edge_closures,test_gap_closures,test_returning_closures) all PASSNotes
The fix should also benefit any pre-bundled npm package that uses the
var X = (...) => …; export { X };pattern whereXis recursive AND a same-named module is namespace-imported elsewhere — the Effect surface has dozens of such shapes.