diff --git a/src/Compilation.zig b/src/Compilation.zig index 5c49e96db2..8787d679e6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3203,8 +3203,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { if (ctx.err.*) |_| return lhs_index < rhs_index; const errors = ctx.zcu.failed_analysis.values(); - const lhs_src_loc = errors[lhs_index].src_loc.upgrade(ctx.zcu); - const rhs_src_loc = errors[rhs_index].src_loc.upgrade(ctx.zcu); + const lhs_src_loc = errors[lhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { + // LHS source location lost, so should never be referenced. Just sort it to the end. + return false; + }; + const rhs_src_loc = errors[rhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { + // RHS source location lost, so should never be referenced. Just sort it to the end. + return true; + }; return if (lhs_src_loc.file_scope != rhs_src_loc.file_scope) std.mem.order( u8, lhs_src_loc.file_scope.sub_file_path, diff --git a/src/Sema.zig b/src/Sema.zig index 9b6ff7cd8e..a679f69a9c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -17729,7 +17729,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat const msg = msg: { const name = name: { // TODO: we should probably store this name in the ZIR to avoid this complexity. - const file, const src_base_node = Module.LazySrcLoc.resolveBaseNode(block.src_base_inst, mod); + const file, const src_base_node = Module.LazySrcLoc.resolveBaseNode(block.src_base_inst, mod).?; const tree = file.getTree(sema.gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ @@ -17757,7 +17757,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat if (!block.is_typeof and !block.is_comptime and sema.func_index != .none) { const msg = msg: { const name = name: { - const file, const src_base_node = Module.LazySrcLoc.resolveBaseNode(block.src_base_inst, mod); + const file, const src_base_node = Module.LazySrcLoc.resolveBaseNode(block.src_base_inst, mod).?; const tree = file.getTree(sema.gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ diff --git a/src/Zcu.zig b/src/Zcu.zig index c78abb69bf..8626a147b6 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -2042,10 +2042,11 @@ pub const LazySrcLoc = struct { .offset = .unneeded, }; - pub fn resolveBaseNode(base_node_inst: InternPool.TrackedInst.Index, zcu: *Zcu) struct { *File, Ast.Node.Index } { + /// Returns `null` if the ZIR instruction has been lost across incremental updates. + pub fn resolveBaseNode(base_node_inst: InternPool.TrackedInst.Index, zcu: *Zcu) ?struct { *File, Ast.Node.Index } { const ip = &zcu.intern_pool; const file_index, const zir_inst = inst: { - const info = base_node_inst.resolveFull(ip) orelse @panic("TODO: resolve source location relative to lost inst"); + const info = base_node_inst.resolveFull(ip) orelse return null; break :inst .{ info.file, info.inst }; }; const file = zcu.fileByIndex(file_index); @@ -2071,7 +2072,15 @@ pub const LazySrcLoc = struct { /// Resolve the file and AST node of `base_node_inst` to get a resolved `SrcLoc`. /// The resulting `SrcLoc` should only be used ephemerally, as it is not correct across incremental updates. pub fn upgrade(lazy: LazySrcLoc, zcu: *Zcu) SrcLoc { - const file, const base_node = resolveBaseNode(lazy.base_node_inst, zcu); + return lazy.upgradeOrLost(zcu).?; + } + + /// Like `upgrade`, but returns `null` if the source location has been lost across incremental updates. + pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc { + const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{ + zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)), + 0, + } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null; return .{ .file_scope = file, .base_node = base_node, diff --git a/src/crash_report.zig b/src/crash_report.zig index d4fe72a8e8..67ec0e0eb0 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -78,7 +78,13 @@ fn dumpStatusReport() !void { const block: *Sema.Block = anal.block; const zcu = anal.sema.pt.zcu; - const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu); + const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse { + const file = zcu.fileByIndex(block.src_base_inst.resolveFile(&zcu.intern_pool)); + try stderr.writeAll("Analyzing lost instruction in file '"); + try writeFilePath(file, stderr); + try stderr.writeAll("'. This should not happen!\n\n"); + return; + }; try stderr.writeAll("Analyzing "); try writeFilePath(file, stderr); @@ -104,7 +110,13 @@ fn dumpStatusReport() !void { while (parent) |curr| { fba.reset(); try stderr.writeAll(" in "); - const cur_block_file, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu); + const cur_block_file, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse { + const cur_block_file = zcu.fileByIndex(curr.block.src_base_inst.resolveFile(&zcu.intern_pool)); + try writeFilePath(cur_block_file, stderr); + try stderr.writeAll("\n > [lost instruction; this should not happen]\n"); + parent = curr.parent; + continue; + }; try writeFilePath(cur_block_file, stderr); try stderr.writeAll("\n > "); print_zir.renderSingleInstruction(