diff --git a/current/CHECKPOINT-FFI.md b/current/CHECKPOINT-FFI.md index 2863fd7..786df2f 100644 --- a/current/CHECKPOINT-FFI.md +++ b/current/CHECKPOINT-FFI.md @@ -852,7 +852,19 @@ plus 2 codegen fixes surfaced along the way.** ## Current state -- 212/212 example tests pass; `zig build test` green. +- 213/213 example tests pass; `zig build test` green. +- issue-0048 (bare `$args` slice loses `.len` across function- + call boundary — root cause: `lazyLowerFunction` did not save/ + restore `pack_arg_nodes` / `pack_param_count` / `pack_arg_types` + / `inline_return_target`, so a lazily lowered callee inside a + pack-fn mono inherited the outer pack maps and `lowerFieldAccess`'s + `.len` intercept folded the callee's same-named param + to the outer mono's arity). FIXED — defer-restore block added to + `lazyLowerFunction`; regression locked in at + `examples/173-pack-bare-args-cross-call.sx`. +- Step 5.0 probe done — nested `() -> Ret callconv(.c) { body }` + parses, `@inner` address-of binds to a fn-pointer, indirect call + works. The trampoline emission pattern is unblocked. - Phase 3.0/3.1/3.2 + M1.0–M1.3 + M2.1–M2.3 + M3 + M4.0 + M4.A all landed. - Pack feature step 1 done (1c.A → 1d.B; commits bb6eca6 → 08feb60). - Pack feature step 2 done — typed `args[$i]` at literal indices diff --git a/src/ir/lower.zig b/src/ir/lower.zig index 6eb1b2e..bc89881 100644 --- a/src/ir/lower.zig +++ b/src/ir/lower.zig @@ -1011,6 +1011,28 @@ pub const Lowering = struct { const saved_jni_env_base = self.jni_env_stack_base; self.jni_env_stack_base = self.jni_env_stack.items.len; defer self.jni_env_stack_base = saved_jni_env_base; + // Pack-fn mono state is lexical to the pack-fn body. A lazily + // lowered callee may share a param NAME with the active pack + // (e.g. `walk(args: []Any)` called from `probe(..$args)`); without + // isolation, `lowerFieldAccess`'s `.len` intercept + // folds the callee's `args.len` to the outer mono's arity and + // bakes the constant into the IR. Same shape for the AST-node + // and per-element-type maps. Null out for the duration of the + // body lowering and restore on exit. + const saved_pan = self.pack_arg_nodes; + const saved_ppc = self.pack_param_count; + const saved_pat = self.pack_arg_types; + const saved_iri = self.inline_return_target; + self.pack_arg_nodes = null; + self.pack_param_count = null; + self.pack_arg_types = null; + self.inline_return_target = null; + defer { + self.pack_arg_nodes = saved_pan; + self.pack_param_count = saved_ppc; + self.pack_arg_types = saved_pat; + self.inline_return_target = saved_iri; + } self.func_defer_base = self.defer_stack.items.len; self.block_terminated = false; self.force_block_value = false;