fix: body-local #run of an unbridged shape fails loudly instead of silent garbage (issue 0182)

The body-local #run fold in emitCall was effectively dead (gated on
args.len==0, but the __ct comptime wrapper always carries the implicit
*Context arg), so every body-local #run fell through to a RUNTIME call:
bridgeable shapes lucked into the right value; an unbridgeable shape
(e.g. [2][]i64) ran over --- storage -> garbage, exit 0, no diagnostic.

Fold any is_comptime callee (gated !enclosing.is_comptime so nested
metatype calls in a comptime wrapper's dead body aren't folded). On a
tryEval bail, distinguish a BRIDGE bail (result can't regToValue-
materialize -> error: comptime init of 'X' failed: <reason> +
comptime_failed, build fails, symmetric with the global #run path) from
an EXECUTION bail (VM can't run the body, e.g. NaN/extern -> runtime
fallthrough, preserving types/0150), via comptime_vm.last_bail_was_bridge
(reset at tryEval entry, set only at regToValue). The const name is
threaded onto the wrapper (comptime_display_name) so the diagnostic reads
the source name, not __ct_N.

Regressions: diagnostics/1204 (negative), comptime/0645 (positive).
Verified by 3 adversarial reviews, suite 801/0.
This commit is contained in:
agra
2026-06-23 19:29:11 +03:00
parent 95c9c0df4c
commit 6c89a0aa3e
15 changed files with 182 additions and 4 deletions

View File

@@ -640,6 +640,13 @@ pub const Function = struct {
/// drops the leftover declaration. See current/PLAN-COMPILER-VM.md (S3).
is_compiler_domain: bool = false,
/// For a body-local `#run` wrapper (`L :: #run f()` → an `is_comptime`
/// `__ct_N` function): the user-facing const NAME the `#run` initializes, so
/// a comptime-init failure can report `comptime init of 'L' failed` (issue
/// 0182) rather than the internal `__ct_N` wrapper name. Null when the `#run`
/// is not bound to a named const (a bare inline `#run`).
comptime_display_name: ?StringId = null,
/// True for an `abi(.naked)` function — no calling-convention
/// prologue/epilogue/frame, no implicit `__sx_ctx`. Its body is a single
/// inline-asm block that reads args from ABI registers and emits its own