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:
@@ -0,0 +1,27 @@
|
||||
// A body-local `#run` const whose comptime function returns a shape the comptime
|
||||
// VM cannot BRIDGE to a host value (here `[2][]i64` — an array of slices) must
|
||||
// FAIL the build with a located `comptime init of '<name>' failed: <reason>`
|
||||
// diagnostic — the SAME loud failure a GLOBAL `#run` const produces — NOT
|
||||
// silently fall back to a runtime call over the wrapper's `---` storage.
|
||||
//
|
||||
// Regression (issue 0182): the body-local `#run` fold left the runtime call in
|
||||
// place when the result couldn't bridge, so `mk()` ran at runtime over
|
||||
// uninitialized storage → garbage, exit 0, no diagnostic (a silent miscompile).
|
||||
// The fix surfaces the BRIDGE bail loudly and gates the build (exit 1). An
|
||||
// EXECUTION bail (a body the VM can't run but the runtime computes correctly,
|
||||
// e.g. `0.0/0.0` → NaN) still falls through to the runtime call — only an
|
||||
// unbridgeable RESULT fails here.
|
||||
#import "modules/std.sx";
|
||||
|
||||
mk :: () -> [2][]i64 {
|
||||
a : []i64 = ---;
|
||||
r : [2][]i64 = ---;
|
||||
r[0] = a;
|
||||
r[1] = a;
|
||||
return r;
|
||||
}
|
||||
|
||||
main :: () {
|
||||
L :: #run mk(); // unbridgeable comptime result → clean build error
|
||||
print("{}\n", L[0][0]);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
error: comptime init of 'L' failed: reg→value: aggregate shape not bridged yet
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user