mem: add explicit bail diagnostics for unhandled raw-pointer interp paths
Comptime fall-through paths used to surface as bare `CannotEvalComptime`
with no hint about the actual limitation. Now each raw-pointer Value
combination that isn't yet wired sets `Interpreter.last_bail_detail`
with a one-line explanation; `printInterpBailDiag` appends it after
the op tag:
error: post-link callback failed: CannotEvalComptime
(op=load/load: comptime load through raw host pointer not supported
(IR type width not threaded)) at .../bundle.sx:N:N
Sites covered: `.load` / `.store` / `.struct_gep` / `.deref` /
`.index_gep` arms for `.int`, `.byte_ptr`, `.heap_ptr` bases;
`storeAtRawPtr`'s catch-all (now exhaustively names every rejected
Value kind); foreign-arg marshalling of unsupported aggregate shapes.
Notable behaviour change: `.deref` through a raw pointer used to
silently return the pointer-as-int unchanged. That looked like a
successful deref to callers — now it errors loudly. Aggregate
passthrough (for `*string` / `*Closure` slot deref) is preserved.
The `storeAtRawPtr` `.int`/`.float` arms still assume 8-byte width —
the Store IR op doesn't carry val's TypeId. Documented inline at the
helper: real-world comptime stores hit 8-byte fields; smaller dests
would clobber. Threading val_ty into Store is left for when a
comptime path actually hits this.
153/153 still passing. The new diagnostics fire when a comptime path
goes through an unhandled shape — verified by reading the bail text
from a synthetic test (separate issue: `#run` silently drops the error
instead of surfacing the diagnostic to the user — out of scope here).
This commit is contained in:
@@ -428,16 +428,18 @@ fn printInterpBailDiag(comp: *const sx.core.Compilation, label: []const u8, err:
|
||||
return;
|
||||
};
|
||||
const op_detail: []const u8 = if (sx.ir.Interpreter.last_bail_builtin) |b| b else op;
|
||||
const explanation = sx.ir.Interpreter.last_bail_detail orelse "";
|
||||
const sep: []const u8 = if (explanation.len > 0) ": " else "";
|
||||
if (sx.ir.Interpreter.last_bail_file) |file| {
|
||||
if (comp.import_sources.get(file)) |source| {
|
||||
const loc = sx.errors.SourceLoc.compute(source, sx.ir.Interpreter.last_bail_offset);
|
||||
std.debug.print("error: {s} failed: {s} (op={s}/{s}) at {s}:{d}:{d}\n", .{ label, @errorName(err), op, op_detail, file, loc.line, loc.col });
|
||||
std.debug.print("error: {s} failed: {s} (op={s}/{s}{s}{s}) at {s}:{d}:{d}\n", .{ label, @errorName(err), op, op_detail, sep, explanation, file, loc.line, loc.col });
|
||||
return;
|
||||
}
|
||||
std.debug.print("error: {s} failed: {s} (op={s}/{s}) at {s}:+{d}\n", .{ label, @errorName(err), op, op_detail, file, sx.ir.Interpreter.last_bail_offset });
|
||||
std.debug.print("error: {s} failed: {s} (op={s}/{s}{s}{s}) at {s}:+{d}\n", .{ label, @errorName(err), op, op_detail, sep, explanation, file, sx.ir.Interpreter.last_bail_offset });
|
||||
return;
|
||||
}
|
||||
std.debug.print("error: {s} failed: {s} (op={s}/{s})\n", .{ label, @errorName(err), op, op_detail });
|
||||
std.debug.print("error: {s} failed: {s} (op={s}/{s}{s}{s})\n", .{ label, @errorName(err), op, op_detail, sep, explanation });
|
||||
}
|
||||
|
||||
fn readSource(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8) ![:0]const u8 {
|
||||
|
||||
Reference in New Issue
Block a user