diff --git a/src/ir/lower/comptime.zig b/src/ir/lower/comptime.zig index 4bb9a412..64820fa4 100644 --- a/src/ir/lower/comptime.zig +++ b/src/ir/lower/comptime.zig @@ -6,9 +6,7 @@ const types = @import("../types.zig"); const inst_mod = @import("../inst.zig"); const unescape = @import("../../unescape.zig"); const parser_mod = @import("../../parser.zig"); -const interp_mod = @import("../interp.zig"); const comptime_vm = @import("../comptime_vm.zig"); -const build_opts = @import("build_opts"); const program_index_mod = @import("../program_index.zig"); const resolver_mod = @import("../resolver.zig"); const ModuleConstInfo = program_index_mod.ModuleConstInfo; @@ -588,34 +586,24 @@ pub fn evalComptimeString(self: *Lowering, expr: *const Node) ?[:0]const u8 { return self.alloc.dupeZ(u8, str) catch null; } - // Case 2: Evaluate via IR interpreter, reusing the parent module. - // The parent's `scanDecls` pass has already registered every - // type / protocol / impl / thunk the comptime call may need - // (Allocator, CAllocator, Context, the per-impl thunks). A - // fresh empty module would only lazy-lower function ASTs and - // would miss the type/protocol registrations, which would break - // `context.allocator.X` — the protocol dispatch chain needs - // those types to resolve struct field layout and the alloc/ - // dealloc thunks at the bottom of the dispatch. + // Case 2: evaluate on the comptime VM (the SOLE evaluator — P5.7), reusing + // the parent module. The parent's `scanDecls` pass has already registered + // every type / protocol / impl / thunk the comptime call may need + // (Allocator, CAllocator, Context, the per-impl thunks); a fresh empty + // module would miss those and break `context.allocator.X`. + // + // Lowering-time IR can be malformed (e.g. a `ret Ref.none` left by an + // unresolved name — see `0737`); the VM is hardened to BAIL (never panic) on + // it, so `tryEval` yields null and we return null. The real user diagnostic + // (the visibility error, …) was already emitted while lowering the inserted + // expression. `regToValue` dupes the result string into `self.alloc`, so it + // outlives the VM's arena. const ct_func_id = self.createComptimeFunction("__insert", expr, .string); - - // NOTE: the comptime VM is intentionally NOT wired at this LOWERING-time - // site. Unlike the emit-time const-init / `#run` folds (which run on fully - // lowered IR), lowering-time IR can be malformed (e.g. a `ret Ref.none` left by - // an unresolved name — see `0737`), and routing that through the VM is out of - // scope until the VM is fully hardened against arbitrary malformed IR. The - // emit-time sites already give the VM full corpus coverage. - var interp = interp_mod.Interpreter.init(self.module, self.alloc); - defer interp.deinit(); - if (self.diagnostics) |d| if (d.import_sources) |sm| interp.setSourceMap(sm); - - const result = interp.call(ct_func_id, &.{}) catch return null; - - const str = result.asString(&interp) orelse switch (result) { + const result = comptime_vm.tryEval(self.alloc, self.module, ct_func_id, null, null) orelse return null; + const str = switch (result) { .string => |s| s, else => return null, }; - return self.alloc.dupeZ(u8, str) catch null; }