ffi issue-0046 fix: save/restore outer state in createComptimeFunction

`createComptimeFunction` wraps a comptime expression into a
fresh fn that the interp executes in isolation. The wrapper
must not inherit the enclosing call's lowering state — any
leaked slot, binding, or scope flag corrupts the wrapper's
own lowering.

Pre-fix, only `func` / `current_block` / `inst_counter` /
`scope` / `current_ctx_ref` were saved. Specifically NOT
saved:

- `inline_return_target` — set by `lowerComptimeCall` for an
  outer comptime body with `return X;`. The wrapper's body
  was lowering through this slot, routing the wrapper's
  `ret` into a basic block from a different function.
- `pack_arg_nodes`, `pack_param_count`, `pack_arg_types` —
  active during a pack-fn mono's body lowering. (Pack-fn
  face of 0046 was already fixed by step 2b moving pack-fn
  calls off the inline path; these saves close a latent
  cross-contamination if any future pack-mono body invokes
  the comptime interp.)
- `comptime_param_nodes` — active during an outer
  `lowerComptimeCall` to bind `$fmt`-style substitutions.
- `block_terminated`, `target_type`, `func_defer_base` — fn-
  local flags that the wrapper's lowering needs fresh.

All eight now save/restore in `createComptimeFunction`. The
wrapper runs in a clean state.

`examples/issue-0046.sx` flips from the
non-deterministic interp panic to "inside\n" + "n=42\n".

204/204 example tests + `zig build test` green. Issue file
marked FIXED with a pointer to the regression test.
This commit is contained in:
agra
2026-05-27 16:57:19 +03:00
parent 13efc565fa
commit 248d6e669c
2 changed files with 57 additions and 2 deletions

View File

@@ -1,3 +1,22 @@
**FIXED.** `createComptimeFunction` now saves/restores the
outer `lowerComptimeCall`'s state — specifically
`inline_return_target`, `pack_arg_nodes`, `pack_param_count`,
`pack_arg_types`, `comptime_param_nodes`, `block_terminated`,
`target_type`, and `func_defer_base` — so the wrapper fn it
builds for the nested comptime expression runs in isolation.
Without the saves, the wrapper inherited an inline-return slot
belonging to a different basic block; the interp executed it
and tripped a null pointer store at `storeAtRawPtr`.
The pack-fn face of this bug (filed as face 2) was fixed
incidentally by step 2b's mono refactor — pack-fn calls
bypass the inline-return-slot setup entirely. Plain
`($x: s32)` comptime fns stay on the inline path; the
`createComptimeFunction` save/restore fix covers that path.
Regression test:
[examples/issue-0046.sx](../examples/issue-0046.sx).
# Symptom
A comptime fn body containing BOTH a nested comptime call