diff --git a/src/Compilation.zig b/src/Compilation.zig index 507cbfc6d5..32243daf69 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2639,7 +2639,7 @@ fn reportMultiModuleErrors(mod: *Module) !void { .root => |pkg| blk: { break :blk try Module.ErrorMsg.init( mod.gpa, - .{ .file_scope = file, .parent_decl_node = 0, .lazy = .entire_file }, + .{ .file_scope = file, .base_node = 0, .lazy = .entire_file }, "root of module {s}", .{pkg.fully_qualified_name}, ); @@ -2651,7 +2651,7 @@ fn reportMultiModuleErrors(mod: *Module) !void { if (omitted > 0) { notes[num_notes] = try Module.ErrorMsg.init( mod.gpa, - .{ .file_scope = file, .parent_decl_node = 0, .lazy = .entire_file }, + .{ .file_scope = file, .base_node = 0, .lazy = .entire_file }, "{} more references omitted", .{omitted}, ); @@ -2660,7 +2660,7 @@ fn reportMultiModuleErrors(mod: *Module) !void { const err = try Module.ErrorMsg.create( mod.gpa, - .{ .file_scope = file, .parent_decl_node = 0, .lazy = .entire_file }, + .{ .file_scope = file, .base_node = 0, .lazy = .entire_file }, "file exists in multiple modules", .{}, ); @@ -3040,29 +3040,26 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { } } - if (comp.module) |module| { - if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) { - const keys = module.compile_log_decls.keys(); - const values = module.compile_log_decls.values(); + if (comp.module) |zcu| { + if (bundle.root_list.items.len == 0 and zcu.compile_log_decls.count() != 0) { + const values = zcu.compile_log_decls.values(); // First one will be the error; subsequent ones will be notes. - const err_decl = module.declPtr(keys[0]); - const src_loc = err_decl.nodeOffsetSrcLoc(values[0], module); - const err_msg = Module.ErrorMsg{ + const src_loc = values[0].src().upgrade(zcu); + const err_msg: Module.ErrorMsg = .{ .src_loc = src_loc, .msg = "found compile log statement", - .notes = try gpa.alloc(Module.ErrorMsg, module.compile_log_decls.count() - 1), + .notes = try gpa.alloc(Module.ErrorMsg, zcu.compile_log_decls.count() - 1), }; defer gpa.free(err_msg.notes); - for (keys[1..], 0..) |key, i| { - const note_decl = module.declPtr(key); - err_msg.notes[i] = .{ - .src_loc = note_decl.nodeOffsetSrcLoc(values[i + 1], module), + for (values[1..], err_msg.notes) |src_info, *note| { + note.* = .{ + .src_loc = src_info.src().upgrade(zcu), .msg = "also here", }; } - try addModuleErrorMsg(module, &bundle, err_msg); + try addModuleErrorMsg(zcu, &bundle, err_msg); } } @@ -3492,7 +3489,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo try module.failed_decls.ensureUnusedCapacity(gpa, 1); module.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( gpa, - decl.srcLoc(module), + decl.navSrcLoc(module).upgrade(module), "unable to update line number: {s}", .{@errorName(err)}, )); @@ -3993,7 +3990,7 @@ fn workerAstGenFile( if (!res.is_pkg) { res.file.addReference(mod.*, .{ .import = .{ .file_scope = file, - .parent_decl_node = 0, + .base_node = 0, .lazy = .{ .token_abs = item.data.token }, } }) catch continue; } @@ -4370,7 +4367,7 @@ fn reportRetryableAstGenError( const src_loc: Module.SrcLoc = switch (src) { .root => .{ .file_scope = file, - .parent_decl_node = 0, + .base_node = 0, .lazy = .entire_file, }, .import => |info| blk: { @@ -4378,7 +4375,7 @@ fn reportRetryableAstGenError( break :blk .{ .file_scope = importing_file, - .parent_decl_node = 0, + .base_node = 0, .lazy = .{ .token_abs = info.import_tok }, }; }, diff --git a/src/InternPool.zig b/src/InternPool.zig index f1c90311c4..3669ab59d1 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -101,8 +101,11 @@ pub const TrackedInst = extern struct { } pub const Index = enum(u32) { _, + pub fn resolveFull(i: TrackedInst.Index, ip: *const InternPool) TrackedInst { + return ip.tracked_insts.keys()[@intFromEnum(i)]; + } pub fn resolve(i: TrackedInst.Index, ip: *const InternPool) Zir.Inst.Index { - return ip.tracked_insts.keys()[@intFromEnum(i)].inst; + return i.resolveFull(ip).inst; } pub fn toOptional(i: TrackedInst.Index) Optional { return @enumFromInt(@intFromEnum(i)); @@ -6954,7 +6957,6 @@ fn finishFuncInstance( const decl_index = try ip.createDecl(gpa, .{ .name = undefined, .src_namespace = fn_owner_decl.src_namespace, - .src_node = fn_owner_decl.src_node, .src_line = fn_owner_decl.src_line, .has_tv = true, .owns_tv = true, diff --git a/src/Module.zig b/src/Module.zig index 283a4f75cc..f857d0997b 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -107,8 +107,17 @@ intern_pool: InternPool = .{}, /// a Decl can have a failed_decls entry but have analysis status of success. failed_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, *ErrorMsg) = .{}, /// Keep track of one `@compileLog` callsite per owner Decl. -/// The value is the AST node index offset from the Decl. -compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, i32) = .{}, +/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`. +compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, extern struct { + base_node_inst: InternPool.TrackedInst.Index, + node_offset: i32, + pub fn src(self: @This()) LazySrcLoc { + return .{ + .base_node_inst = self.base_node_inst, + .offset = LazySrcLoc.Offset.nodeOffset(self.node_offset), + }; + } +}) = .{}, /// Using a map here for consistency with the other fields here. /// The ErrorMsg memory is owned by the `File`, using Module's general purpose allocator. failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{}, @@ -257,9 +266,6 @@ pub const Export = struct { src: LazySrcLoc, /// The Decl that performs the export. Note that this is *not* the Decl being exported. owner_decl: Decl.Index, - /// The Decl containing the export statement. Inline function calls - /// may cause this to be different from the owner_decl. - src_decl: Decl.Index, exported: Exported, status: enum { in_progress, @@ -278,12 +284,7 @@ pub const Export = struct { }; pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc { - const src_decl = mod.declPtr(exp.src_decl); - return .{ - .file_scope = src_decl.getFileScope(mod), - .parent_decl_node = src_decl.src_node, - .lazy = exp.src, - }; + return exp.src.upgrade(mod); } }; @@ -343,9 +344,6 @@ pub const Decl = struct { /// there is no parent. src_namespace: Namespace.Index, - /// The AST node index of this declaration. - /// Must be recomputed when the corresponding source file is modified. - src_node: Ast.Node.Index, /// Line number corresponding to `src_node`. Stored separately so that source files /// do not need to be loaded into memory in order to compute debug line numbers. /// This value is absolute. @@ -417,26 +415,6 @@ pub const Decl = struct { return extra.data.getBodies(@intCast(extra.end), zir); } - pub fn relativeToNodeIndex(decl: Decl, offset: i32) Ast.Node.Index { - return @bitCast(offset + @as(i32, @bitCast(decl.src_node))); - } - - pub fn nodeIndexToRelative(decl: Decl, node_index: Ast.Node.Index) i32 { - return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(decl.src_node)); - } - - pub fn srcLoc(decl: Decl, zcu: *Zcu) SrcLoc { - return decl.nodeOffsetSrcLoc(0, zcu); - } - - pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32, zcu: *Zcu) SrcLoc { - return .{ - .file_scope = decl.getFileScope(zcu), - .parent_decl_node = decl.src_node, - .lazy = LazySrcLoc.nodeOffset(node_offset), - }; - } - pub fn renderFullyQualifiedName(decl: Decl, zcu: *Zcu, writer: anytype) !void { if (decl.name_fully_qualified) { try writer.print("{}", .{decl.name.fmt(&zcu.intern_pool)}); @@ -551,101 +529,6 @@ pub const Decl = struct { return decl.typeOf(zcu).abiAlignment(zcu); } - /// Upgrade a `LazySrcLoc` to a `SrcLoc` based on the `Decl` provided. - pub fn toSrcLoc(decl: *Decl, lazy: LazySrcLoc, mod: *Module) SrcLoc { - return switch (lazy) { - .unneeded, - .entire_file, - .byte_abs, - .token_abs, - .node_abs, - => .{ - .file_scope = decl.getFileScope(mod), - .parent_decl_node = 0, - .lazy = lazy, - }, - - .byte_offset, - .token_offset, - .node_offset, - .node_offset_main_token, - .node_offset_initializer, - .node_offset_var_decl_ty, - .node_offset_var_decl_align, - .node_offset_var_decl_section, - .node_offset_var_decl_addrspace, - .node_offset_var_decl_init, - .node_offset_builtin_call_arg0, - .node_offset_builtin_call_arg1, - .node_offset_builtin_call_arg2, - .node_offset_builtin_call_arg3, - .node_offset_builtin_call_arg4, - .node_offset_builtin_call_arg5, - .node_offset_ptrcast_operand, - .node_offset_array_access_index, - .node_offset_slice_ptr, - .node_offset_slice_start, - .node_offset_slice_end, - .node_offset_slice_sentinel, - .node_offset_call_func, - .node_offset_field_name, - .node_offset_field_name_init, - .node_offset_deref_ptr, - .node_offset_asm_source, - .node_offset_asm_ret_ty, - .node_offset_if_cond, - .node_offset_bin_op, - .node_offset_bin_lhs, - .node_offset_bin_rhs, - .node_offset_switch_operand, - .node_offset_switch_special_prong, - .node_offset_switch_range, - .node_offset_switch_prong_capture, - .node_offset_switch_prong_tag_capture, - .node_offset_fn_type_align, - .node_offset_fn_type_addrspace, - .node_offset_fn_type_section, - .node_offset_fn_type_cc, - .node_offset_fn_type_ret_ty, - .node_offset_param, - .token_offset_param, - .node_offset_anyframe_type, - .node_offset_lib_name, - .node_offset_array_type_len, - .node_offset_array_type_sentinel, - .node_offset_array_type_elem, - .node_offset_un_op, - .node_offset_ptr_elem, - .node_offset_ptr_sentinel, - .node_offset_ptr_align, - .node_offset_ptr_addrspace, - .node_offset_ptr_bitoffset, - .node_offset_ptr_hostsize, - .node_offset_container_tag, - .node_offset_field_default, - .node_offset_init_ty, - .node_offset_store_ptr, - .node_offset_store_operand, - .node_offset_return_operand, - .for_input, - .for_capture_from_input, - .array_cat_lhs, - .array_cat_rhs, - => .{ - .file_scope = decl.getFileScope(mod), - .parent_decl_node = decl.src_node, - .lazy = lazy, - }, - inline .call_arg, - .fn_proto_param, - => |x| .{ - .file_scope = decl.getFileScope(mod), - .parent_decl_node = mod.declPtr(x.decl).src_node, - .lazy = lazy, - }, - }; - } - pub fn declPtrType(decl: Decl, zcu: *Zcu) !Type { assert(decl.has_tv); const decl_ty = decl.typeOf(zcu); @@ -661,6 +544,23 @@ pub const Decl = struct { }, }); } + + /// Returns the source location of this `Decl`. + /// Asserts that this `Decl` corresponds to what will in future be a `Nav` (Named + /// Addressable Value): a source-level declaration or generic instantiation. + pub fn navSrcLoc(decl: Decl, zcu: *Zcu) LazySrcLoc { + return .{ + .base_node_inst = decl.zir_decl_index.unwrap() orelse inst: { + // generic instantiation + assert(decl.has_tv); + assert(decl.owns_tv); + const owner = zcu.funcInfo(decl.val.toIntern()).generic_owner; + const generic_owner_decl = zcu.declPtr(zcu.funcInfo(owner).owner_decl); + break :inst generic_owner_decl.zir_decl_index.unwrap().?; + }, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }; + } }; /// This state is attached to every Decl when Module emit_h is non-null. @@ -1137,18 +1037,17 @@ pub const ErrorMsg = struct { /// Canonical reference to a position within a source file. pub const SrcLoc = struct { file_scope: *File, - /// Might be 0 depending on tag of `lazy`. - parent_decl_node: Ast.Node.Index, - /// Relative to `parent_decl_node`. - lazy: LazySrcLoc, + base_node: Ast.Node.Index, + /// Relative to `base_node`. + lazy: LazySrcLoc.Offset, - pub fn declSrcToken(src_loc: SrcLoc) Ast.TokenIndex { + pub fn baseSrcToken(src_loc: SrcLoc) Ast.TokenIndex { const tree = src_loc.file_scope.tree; - return tree.firstToken(src_loc.parent_decl_node); + return tree.firstToken(src_loc.base_node); } - pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index { - return @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node))); + pub fn relativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index { + return @bitCast(offset + @as(i32, @bitCast(src_loc.base_node))); } pub const Span = Ast.Span; @@ -1172,14 +1071,14 @@ pub const SrcLoc = struct { }, .byte_offset => |byte_off| { const tree = try src_loc.file_scope.getTree(gpa); - const tok_index = src_loc.declSrcToken(); + const tok_index = src_loc.baseSrcToken(); const start = tree.tokens.items(.start)[tok_index] + byte_off; const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); return Span{ .start = start, .end = end, .main = start }; }, .token_offset => |tok_off| { const tree = try src_loc.file_scope.getTree(gpa); - const tok_index = src_loc.declSrcToken() + tok_off; + const tok_index = src_loc.baseSrcToken() + tok_off; const start = tree.tokens.items(.start)[tok_index]; const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); return Span{ .start = start, .end = end, .main = start }; @@ -1187,25 +1086,25 @@ pub const SrcLoc = struct { .node_offset => |traced_off| { const node_off = traced_off.x; const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); assert(src_loc.file_scope.tree_loaded); return tree.nodeToSpan(node); }, .node_offset_main_token => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const main_token = tree.nodes.items(.main_token)[node]; return tree.tokensToSpan(main_token, main_token, main_token); }, .node_offset_bin_op => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); assert(src_loc.file_scope.tree_loaded); return tree.nodeToSpan(node); }, .node_offset_initializer => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); return tree.tokensToSpan( tree.firstToken(node) - 3, tree.lastToken(node), @@ -1214,7 +1113,7 @@ pub const SrcLoc = struct { }, .node_offset_var_decl_ty => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const node_tags = tree.nodes.items(.tag); const full = switch (node_tags[node]) { .global_var_decl, @@ -1238,41 +1137,51 @@ pub const SrcLoc = struct { }, .node_offset_var_decl_align => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullVarDecl(node).?; return tree.nodeToSpan(full.ast.align_node); }, .node_offset_var_decl_section => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullVarDecl(node).?; return tree.nodeToSpan(full.ast.section_node); }, .node_offset_var_decl_addrspace => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullVarDecl(node).?; return tree.nodeToSpan(full.ast.addrspace_node); }, .node_offset_var_decl_init => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullVarDecl(node).?; return tree.nodeToSpan(full.ast.init_node); }, - .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0), - .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1), - .node_offset_builtin_call_arg2 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 2), - .node_offset_builtin_call_arg3 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 3), - .node_offset_builtin_call_arg4 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 4), - .node_offset_builtin_call_arg5 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 5), + .node_offset_builtin_call_arg => |builtin_arg| { + const tree = try src_loc.file_scope.getTree(gpa); + const node_datas = tree.nodes.items(.data); + const node_tags = tree.nodes.items(.tag); + const node = src_loc.relativeToNodeIndex(builtin_arg.builtin_call_node); + const param = switch (node_tags[node]) { + .builtin_call_two, .builtin_call_two_comma => switch (builtin_arg.arg_index) { + 0 => node_datas[node].lhs, + 1 => node_datas[node].rhs, + else => unreachable, + }, + .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + builtin_arg.arg_index], + else => unreachable, + }; + return tree.nodeToSpan(param); + }, .node_offset_ptrcast_operand => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const main_tokens = tree.nodes.items(.main_token); const node_datas = tree.nodes.items(.data); const node_tags = tree.nodes.items(.tag); - var node = src_loc.declRelativeToNodeIndex(node_off); + var node = src_loc.relativeToNodeIndex(node_off); while (true) { switch (node_tags[node]) { .builtin_call_two, .builtin_call_two_comma => {}, @@ -1304,7 +1213,7 @@ pub const SrcLoc = struct { .node_offset_array_access_index => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node_datas = tree.nodes.items(.data); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); return tree.nodeToSpan(node_datas[node].rhs); }, .node_offset_slice_ptr, @@ -1313,7 +1222,7 @@ pub const SrcLoc = struct { .node_offset_slice_sentinel, => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullSlice(node).?; const part_node = switch (src_loc.lazy) { .node_offset_slice_ptr => full.ast.sliced, @@ -1326,7 +1235,7 @@ pub const SrcLoc = struct { }, .node_offset_call_func => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullCall(&buf, node).?; return tree.nodeToSpan(full.ast.fn_expr); @@ -1335,7 +1244,7 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(gpa); const node_datas = tree.nodes.items(.data); const node_tags = tree.nodes.items(.tag); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const tok_index = switch (node_tags[node]) { .field_access => node_datas[node].rhs, @@ -1359,7 +1268,7 @@ pub const SrcLoc = struct { }, .node_offset_field_name_init => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const tok_index = tree.firstToken(node) - 2; const start = tree.tokens.items(.start)[tok_index]; const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); @@ -1367,18 +1276,18 @@ pub const SrcLoc = struct { }, .node_offset_deref_ptr => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); return tree.nodeToSpan(node); }, .node_offset_asm_source => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullAsm(node).?; return tree.nodeToSpan(full.ast.template); }, .node_offset_asm_ret_ty => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullAsm(node).?; const asm_output = full.outputs[0]; const node_datas = tree.nodes.items(.data); @@ -1387,7 +1296,7 @@ pub const SrcLoc = struct { .node_offset_if_cond => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const node_tags = tree.nodes.items(.tag); const src_node = switch (node_tags[node]) { .if_simple, @@ -1416,7 +1325,7 @@ pub const SrcLoc = struct { }, .for_input => |for_input| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(for_input.for_node_offset); + const node = src_loc.relativeToNodeIndex(for_input.for_node_offset); const for_full = tree.fullFor(node).?; const src_node = for_full.ast.inputs[for_input.input_index]; return tree.nodeToSpan(src_node); @@ -1424,7 +1333,7 @@ pub const SrcLoc = struct { .for_capture_from_input => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const token_tags = tree.tokens.items(.tag); - const input_node = src_loc.declRelativeToNodeIndex(node_off); + const input_node = src_loc.relativeToNodeIndex(node_off); // We have to actually linear scan the whole AST to find the for loop // that contains this input. const node_tags = tree.nodes.items(.tag); @@ -1465,7 +1374,7 @@ pub const SrcLoc = struct { }, .call_arg => |call_arg| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset); + const node = src_loc.relativeToNodeIndex(call_arg.call_node_offset); var buf: [2]Ast.Node.Index = undefined; const call_full = tree.fullCall(buf[0..1], node) orelse { const node_tags = tree.nodes.items(.tag); @@ -1501,43 +1410,49 @@ pub const SrcLoc = struct { }; return tree.nodeToSpan(call_full.ast.params[call_arg.arg_index]); }, - .fn_proto_param => |fn_proto_param| { + .fn_proto_param, .fn_proto_param_type => |fn_proto_param| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(fn_proto_param.fn_proto_node_offset); + const node = src_loc.relativeToNodeIndex(fn_proto_param.fn_proto_node_offset); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; var it = full.iterate(tree); var i: usize = 0; while (it.next()) |param| : (i += 1) { - if (i == fn_proto_param.param_index) { - if (param.anytype_ellipsis3) |token| return tree.tokenToSpan(token); - const first_token = param.comptime_noalias orelse - param.name_token orelse - tree.firstToken(param.type_expr); - return tree.tokensToSpan( - first_token, - tree.lastToken(param.type_expr), - first_token, - ); + if (i != fn_proto_param.param_index) continue; + + switch (src_loc.lazy) { + .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| { + return tree.tokenToSpan(tok); + } else { + return tree.nodeToSpan(param.type_expr); + }, + .fn_proto_param => if (param.anytype_ellipsis3) |tok| { + const first = param.comptime_noalias orelse param.name_token orelse tok; + return tree.tokensToSpan(first, tok, first); + } else { + const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr); + return tree.tokensToSpan(first, tree.lastToken(param.type_expr), first); + }, + else => unreachable, } } unreachable; }, .node_offset_bin_lhs => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const node_datas = tree.nodes.items(.data); return tree.nodeToSpan(node_datas[node].lhs); }, .node_offset_bin_rhs => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const node_datas = tree.nodes.items(.data); return tree.nodeToSpan(node_datas[node].rhs); }, .array_cat_lhs, .array_cat_rhs => |cat| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(cat.array_cat_offset); + const node = src_loc.relativeToNodeIndex(cat.array_cat_offset); const node_datas = tree.nodes.items(.data); const arr_node = if (src_loc.lazy == .array_cat_lhs) node_datas[node].lhs @@ -1565,14 +1480,14 @@ pub const SrcLoc = struct { .node_offset_switch_operand => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const node_datas = tree.nodes.items(.data); return tree.nodeToSpan(node_datas[node].lhs); }, .node_offset_switch_special_prong => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const switch_node = src_loc.declRelativeToNodeIndex(node_off); + const switch_node = src_loc.relativeToNodeIndex(node_off); const node_datas = tree.nodes.items(.data); const node_tags = tree.nodes.items(.tag); const main_tokens = tree.nodes.items(.main_token); @@ -1592,7 +1507,7 @@ pub const SrcLoc = struct { .node_offset_switch_range => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const switch_node = src_loc.declRelativeToNodeIndex(node_off); + const switch_node = src_loc.relativeToNodeIndex(node_off); const node_datas = tree.nodes.items(.data); const node_tags = tree.nodes.items(.tag); const main_tokens = tree.nodes.items(.main_token); @@ -1613,56 +1528,30 @@ pub const SrcLoc = struct { } } else unreachable; }, - .node_offset_switch_prong_capture, - .node_offset_switch_prong_tag_capture, - => |node_off| { - const tree = try src_loc.file_scope.getTree(gpa); - const case_node = src_loc.declRelativeToNodeIndex(node_off); - const case = tree.fullSwitchCase(case_node).?; - const token_tags = tree.tokens.items(.tag); - const start_tok = switch (src_loc.lazy) { - .node_offset_switch_prong_capture => case.payload_token.?, - .node_offset_switch_prong_tag_capture => blk: { - var tok = case.payload_token.?; - if (token_tags[tok] == .asterisk) tok += 1; - tok += 2; // skip over comma - break :blk tok; - }, - else => unreachable, - }; - const end_tok = switch (token_tags[start_tok]) { - .asterisk => start_tok + 1, - else => start_tok, - }; - const start = tree.tokens.items(.start)[start_tok]; - const end_start = tree.tokens.items(.start)[end_tok]; - const end = end_start + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); - return Span{ .start = start, .end = end, .main = start }; - }, .node_offset_fn_type_align => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; return tree.nodeToSpan(full.ast.align_expr); }, .node_offset_fn_type_addrspace => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; return tree.nodeToSpan(full.ast.addrspace_expr); }, .node_offset_fn_type_section => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; return tree.nodeToSpan(full.ast.section_expr); }, .node_offset_fn_type_cc => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; return tree.nodeToSpan(full.ast.callconv_expr); @@ -1670,7 +1559,7 @@ pub const SrcLoc = struct { .node_offset_fn_type_ret_ty => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; return tree.nodeToSpan(full.ast.return_type); @@ -1678,7 +1567,7 @@ pub const SrcLoc = struct { .node_offset_param => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const token_tags = tree.tokens.items(.tag); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); var first_tok = tree.firstToken(node); while (true) switch (token_tags[first_tok - 1]) { @@ -1694,7 +1583,7 @@ pub const SrcLoc = struct { .token_offset_param => |token_off| { const tree = try src_loc.file_scope.getTree(gpa); const token_tags = tree.tokens.items(.tag); - const main_token = tree.nodes.items(.main_token)[src_loc.parent_decl_node]; + const main_token = tree.nodes.items(.main_token)[src_loc.base_node]; const tok_index = @as(Ast.TokenIndex, @bitCast(token_off + @as(i32, @bitCast(main_token)))); var first_tok = tok_index; @@ -1712,13 +1601,13 @@ pub const SrcLoc = struct { .node_offset_anyframe_type => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node_datas = tree.nodes.items(.data); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); return tree.nodeToSpan(node_datas[parent_node].rhs); }, .node_offset_lib_name => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, parent_node).?; const tok_index = full.lib_name.?; @@ -1729,21 +1618,21 @@ pub const SrcLoc = struct { .node_offset_array_type_len => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullArrayType(parent_node).?; return tree.nodeToSpan(full.ast.elem_count); }, .node_offset_array_type_sentinel => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullArrayType(parent_node).?; return tree.nodeToSpan(full.ast.sentinel); }, .node_offset_array_type_elem => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullArrayType(parent_node).?; return tree.nodeToSpan(full.ast.elem_type); @@ -1751,48 +1640,48 @@ pub const SrcLoc = struct { .node_offset_un_op => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node_datas = tree.nodes.items(.data); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); return tree.nodeToSpan(node_datas[node].lhs); }, .node_offset_ptr_elem => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; return tree.nodeToSpan(full.ast.child_type); }, .node_offset_ptr_sentinel => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; return tree.nodeToSpan(full.ast.sentinel); }, .node_offset_ptr_align => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; return tree.nodeToSpan(full.ast.align_node); }, .node_offset_ptr_addrspace => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; return tree.nodeToSpan(full.ast.addrspace_node); }, .node_offset_ptr_bitoffset => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; return tree.nodeToSpan(full.ast.bit_range_start); }, .node_offset_ptr_hostsize => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; return tree.nodeToSpan(full.ast.bit_range_end); @@ -1800,7 +1689,7 @@ pub const SrcLoc = struct { .node_offset_container_tag => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node_tags = tree.nodes.items(.tag); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); switch (node_tags[parent_node]) { .container_decl_arg, .container_decl_arg_trailing => { @@ -1822,7 +1711,7 @@ pub const SrcLoc = struct { .node_offset_field_default => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node_tags = tree.nodes.items(.tag); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); const full: Ast.full.ContainerField = switch (node_tags[parent_node]) { .container_field => tree.containerField(parent_node), @@ -1833,7 +1722,7 @@ pub const SrcLoc = struct { }, .node_offset_init_ty => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const parent_node = src_loc.relativeToNodeIndex(node_off); var buf: [2]Ast.Node.Index = undefined; const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init| @@ -1846,7 +1735,7 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(gpa); const node_tags = tree.nodes.items(.tag); const node_datas = tree.nodes.items(.data); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); switch (node_tags[node]) { .assign => { @@ -1859,7 +1748,7 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(gpa); const node_tags = tree.nodes.items(.tag); const node_datas = tree.nodes.items(.data); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); switch (node_tags[node]) { .assign => { @@ -1870,7 +1759,7 @@ pub const SrcLoc = struct { }, .node_offset_return_operand => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); - const node = src_loc.declRelativeToNodeIndex(node_off); + const node = src_loc.relativeToNodeIndex(node_off); const node_tags = tree.nodes.items(.tag); const node_datas = tree.nodes.items(.data); if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) { @@ -1878,381 +1767,629 @@ pub const SrcLoc = struct { } return tree.nodeToSpan(node); }, - } - } + .container_field_name, + .container_field_value, + .container_field_type, + .container_field_align, + => |field_idx| { + const tree = try src_loc.file_scope.getTree(gpa); + const node = src_loc.relativeToNodeIndex(0); + var buf: [2]Ast.Node.Index = undefined; + const container_decl = tree.fullContainerDecl(&buf, node) orelse + return tree.nodeToSpan(node); - pub fn byteOffsetBuiltinCallArg( - src_loc: SrcLoc, - gpa: Allocator, - node_off: i32, - arg_index: u32, - ) !Span { - const tree = try src_loc.file_scope.getTree(gpa); - const node_datas = tree.nodes.items(.data); - const node_tags = tree.nodes.items(.tag); - const node = src_loc.declRelativeToNodeIndex(node_off); - const param = switch (node_tags[node]) { - .builtin_call_two, .builtin_call_two_comma => switch (arg_index) { - 0 => node_datas[node].lhs, - 1 => node_datas[node].rhs, - else => unreachable, + var cur_field_idx: usize = 0; + for (container_decl.ast.members) |member_node| { + const field = tree.fullContainerField(member_node) orelse continue; + if (cur_field_idx < field_idx) { + cur_field_idx += 1; + continue; + } + const field_component_node = switch (src_loc.lazy) { + .container_field_name => 0, + .container_field_value => field.ast.value_expr, + .container_field_type => field.ast.type_expr, + .container_field_align => field.ast.align_expr, + else => unreachable, + }; + if (field_component_node == 0) { + return tree.tokenToSpan(field.ast.main_token); + } else { + return tree.nodeToSpan(field_component_node); + } + } else unreachable; }, - .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + arg_index], - else => unreachable, - }; - return tree.nodeToSpan(param); + .init_elem => |init_elem| { + const tree = try src_loc.file_scope.getTree(gpa); + const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset); + var buf: [2]Ast.Node.Index = undefined; + if (tree.fullArrayInit(&buf, init_node)) |full| { + const elem_node = full.ast.elements[init_elem.elem_index]; + return tree.nodeToSpan(elem_node); + } else if (tree.fullStructInit(&buf, init_node)) |full| { + const field_node = full.ast.fields[init_elem.elem_index]; + return tree.tokensToSpan( + tree.firstToken(field_node) - 3, + tree.lastToken(field_node), + tree.nodes.items(.main_token)[field_node] - 2, + ); + } else unreachable; + }, + .init_field_name, + .init_field_linkage, + .init_field_section, + .init_field_visibility, + .init_field_rw, + .init_field_locality, + .init_field_cache, + .init_field_library, + .init_field_thread_local, + => |builtin_call_node| { + const wanted = switch (src_loc.lazy) { + .init_field_name => "name", + .init_field_linkage => "linkage", + .init_field_section => "section", + .init_field_visibility => "visibility", + .init_field_rw => "rw", + .init_field_locality => "locality", + .init_field_cache => "cache", + .init_field_library => "library", + .init_field_thread_local => "thread_local", + else => unreachable, + }; + const tree = try src_loc.file_scope.getTree(gpa); + const node_datas = tree.nodes.items(.data); + const node_tags = tree.nodes.items(.tag); + const node = src_loc.relativeToNodeIndex(builtin_call_node); + const arg_node = switch (node_tags[node]) { + .builtin_call_two, .builtin_call_two_comma => node_datas[node].rhs, + .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + 1], + else => unreachable, + }; + var buf: [2]Ast.Node.Index = undefined; + const full = tree.fullStructInit(&buf, arg_node) orelse + return tree.nodeToSpan(arg_node); + for (full.ast.fields) |field_node| { + // . IDENTIFIER = field_node + const name_token = tree.firstToken(field_node) - 2; + const name = tree.tokenSlice(name_token); + if (std.mem.eql(u8, name, wanted)) { + return tree.tokensToSpan( + name_token - 1, + tree.lastToken(field_node), + tree.nodes.items(.main_token)[field_node] - 2, + ); + } + } + return tree.nodeToSpan(arg_node); + }, + .switch_case_item, + .switch_case_item_range_first, + .switch_case_item_range_last, + .switch_capture, + .switch_tag_capture, + => { + const switch_node_offset, const want_case_idx = switch (src_loc.lazy) { + .switch_case_item, + .switch_case_item_range_first, + .switch_case_item_range_last, + => |x| .{ x.switch_node_offset, x.case_idx }, + .switch_capture, + .switch_tag_capture, + => |x| .{ x.switch_node_offset, x.case_idx }, + else => unreachable, + }; + + const tree = try src_loc.file_scope.getTree(gpa); + const node_datas = tree.nodes.items(.data); + const node_tags = tree.nodes.items(.tag); + const main_tokens = tree.nodes.items(.main_token); + const switch_node = src_loc.relativeToNodeIndex(switch_node_offset); + const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); + const case_nodes = tree.extra_data[extra.start..extra.end]; + + var multi_i: u32 = 0; + var scalar_i: u32 = 0; + const case = for (case_nodes) |case_node| { + const case = tree.fullSwitchCase(case_node).?; + const is_special = special: { + if (case.ast.values.len == 0) break :special true; + if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) { + break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"); + } + break :special false; + }; + if (is_special) { + if (want_case_idx.isSpecial()) { + break case; + } + } + + const is_multi = case.ast.values.len != 1 or + node_tags[case.ast.values[0]] == .switch_range; + + if (!want_case_idx.isSpecial()) switch (want_case_idx.kind) { + .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case, + .multi => if (is_multi and want_case_idx.index == multi_i) break case, + }; + + if (is_multi) { + multi_i += 1; + } else { + scalar_i += 1; + } + } else unreachable; + + const want_item = switch (src_loc.lazy) { + .switch_case_item, + .switch_case_item_range_first, + .switch_case_item_range_last, + => |x| x.item_idx, + .switch_capture, .switch_tag_capture => { + const token_tags = tree.tokens.items(.tag); + const start = switch (src_loc.lazy) { + .switch_capture => case.payload_token.?, + .switch_tag_capture => tok: { + var tok = case.payload_token.?; + if (token_tags[tok] == .asterisk) tok += 1; + tok += 2; // skip over comma + break :tok tok; + }, + else => unreachable, + }; + const end = switch (token_tags[start]) { + .asterisk => start + 1, + else => start, + }; + return tree.tokensToSpan(start, end, start); + }, + else => unreachable, + }; + + switch (want_item.kind) { + .single => { + var item_i: u32 = 0; + for (case.ast.values) |item_node| { + if (node_tags[item_node] == .switch_range) continue; + if (item_i != want_item.index) { + item_i += 1; + continue; + } + return tree.nodeToSpan(item_node); + } else unreachable; + }, + .range => { + var range_i: u32 = 0; + for (case.ast.values) |item_node| { + if (node_tags[item_node] != .switch_range) continue; + if (range_i != want_item.index) { + range_i += 1; + continue; + } + return switch (src_loc.lazy) { + .switch_case_item => tree.nodeToSpan(item_node), + .switch_case_item_range_first => tree.nodeToSpan(node_datas[item_node].lhs), + .switch_case_item_range_last => tree.nodeToSpan(node_datas[item_node].rhs), + else => unreachable, + }; + } else unreachable; + }, + } + }, + } } }; -/// Resolving a source location into a byte offset may require doing work -/// that we would rather not do unless the error actually occurs. -/// Therefore we need a data structure that contains the information necessary -/// to lazily produce a `SrcLoc` as required. -/// Most of the offsets in this data structure are relative to the containing Decl. -/// This makes the source location resolve properly even when a Decl gets -/// shifted up or down in the file, as long as the Decl's contents itself -/// do not change. -pub const LazySrcLoc = union(enum) { - /// When this tag is set, the code that constructed this `LazySrcLoc` is asserting - /// that all code paths which would need to resolve the source location are - /// unreachable. If you are debugging this tag incorrectly being this value, - /// look into using reverse-continue with a memory watchpoint to see where the - /// value is being set to this tag. - unneeded, - /// Means the source location points to an entire file; not any particular - /// location within the file. `file_scope` union field will be active. - entire_file, - /// The source location points to a byte offset within a source file, - /// offset from 0. The source file is determined contextually. - /// Inside a `SrcLoc`, the `file_scope` union field will be active. - byte_abs: u32, - /// The source location points to a token within a source file, - /// offset from 0. The source file is determined contextually. - /// Inside a `SrcLoc`, the `file_scope` union field will be active. - token_abs: u32, - /// The source location points to an AST node within a source file, - /// offset from 0. The source file is determined contextually. - /// Inside a `SrcLoc`, the `file_scope` union field will be active. - node_abs: u32, - /// The source location points to a byte offset within a source file, - /// offset from the byte offset of the Decl within the file. - /// The Decl is determined contextually. - byte_offset: u32, - /// This data is the offset into the token list from the Decl token. - /// The Decl is determined contextually. - token_offset: u32, - /// The source location points to an AST node, which is this value offset - /// from its containing Decl node AST index. - /// The Decl is determined contextually. - node_offset: TracedOffset, - /// The source location points to the main token of an AST node, found - /// by taking this AST node index offset from the containing Decl AST node. - /// The Decl is determined contextually. - node_offset_main_token: i32, - /// The source location points to the beginning of a struct initializer. - /// The Decl is determined contextually. - node_offset_initializer: i32, - /// The source location points to a variable declaration type expression, - /// found by taking this AST node index offset from the containing - /// Decl AST node, which points to a variable declaration AST node. Next, navigate - /// to the type expression. - /// The Decl is determined contextually. - node_offset_var_decl_ty: i32, - /// The source location points to the alignment expression of a var decl. - /// The Decl is determined contextually. - node_offset_var_decl_align: i32, - /// The source location points to the linksection expression of a var decl. - /// The Decl is determined contextually. - node_offset_var_decl_section: i32, - /// The source location points to the addrspace expression of a var decl. - /// The Decl is determined contextually. - node_offset_var_decl_addrspace: i32, - /// The source location points to the initializer of a var decl. - /// The Decl is determined contextually. - node_offset_var_decl_init: i32, - /// The source location points to the first parameter of a builtin - /// function call, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a builtin call AST node. Next, navigate - /// to the first parameter. - /// The Decl is determined contextually. - node_offset_builtin_call_arg0: i32, - /// Same as `node_offset_builtin_call_arg0` except arg index 1. - node_offset_builtin_call_arg1: i32, - node_offset_builtin_call_arg2: i32, - node_offset_builtin_call_arg3: i32, - node_offset_builtin_call_arg4: i32, - node_offset_builtin_call_arg5: i32, - /// Like `node_offset_builtin_call_arg0` but recurses through arbitrarily many calls - /// to pointer cast builtins. - node_offset_ptrcast_operand: i32, - /// The source location points to the index expression of an array access - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an array access AST node. Next, navigate - /// to the index expression. - /// The Decl is determined contextually. - node_offset_array_access_index: i32, - /// The source location points to the LHS of a slice expression - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a slice AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_slice_ptr: i32, - /// The source location points to start expression of a slice expression - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a slice AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_slice_start: i32, - /// The source location points to the end expression of a slice - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a slice AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_slice_end: i32, - /// The source location points to the sentinel expression of a slice - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a slice AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_slice_sentinel: i32, - /// The source location points to the callee expression of a function - /// call expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function call AST node. Next, navigate - /// to the callee expression. - /// The Decl is determined contextually. - node_offset_call_func: i32, - /// The payload is offset from the containing Decl AST node. - /// The source location points to the field name of: - /// * a field access expression (`a.b`), or - /// * the callee of a method call (`a.b()`) - /// The Decl is determined contextually. - node_offset_field_name: i32, - /// The payload is offset from the containing Decl AST node. - /// The source location points to the field name of the operand ("b" node) - /// of a field initialization expression (`.a = b`) - /// The Decl is determined contextually. - node_offset_field_name_init: i32, - /// The source location points to the pointer of a pointer deref expression, - /// found by taking this AST node index offset from the containing - /// Decl AST node, which points to a pointer deref AST node. Next, navigate - /// to the pointer expression. - /// The Decl is determined contextually. - node_offset_deref_ptr: i32, - /// The source location points to the assembly source code of an inline assembly - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to inline assembly AST node. Next, navigate - /// to the asm template source code. - /// The Decl is determined contextually. - node_offset_asm_source: i32, - /// The source location points to the return type of an inline assembly - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to inline assembly AST node. Next, navigate - /// to the return type expression. - /// The Decl is determined contextually. - node_offset_asm_ret_ty: i32, - /// The source location points to the condition expression of an if - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an if expression AST node. Next, navigate - /// to the condition expression. - /// The Decl is determined contextually. - node_offset_if_cond: i32, - /// The source location points to a binary expression, such as `a + b`, found - /// by taking this AST node index offset from the containing Decl AST node. - /// The Decl is determined contextually. - node_offset_bin_op: i32, - /// The source location points to the LHS of a binary expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a binary expression AST node. Next, navigate to the LHS. - /// The Decl is determined contextually. - node_offset_bin_lhs: i32, - /// The source location points to the RHS of a binary expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a binary expression AST node. Next, navigate to the RHS. - /// The Decl is determined contextually. - node_offset_bin_rhs: i32, - /// The source location points to the operand of a switch expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a switch expression AST node. Next, navigate to the operand. - /// The Decl is determined contextually. - node_offset_switch_operand: i32, - /// The source location points to the else/`_` prong of a switch expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a switch expression AST node. Next, navigate to the else/`_` prong. - /// The Decl is determined contextually. - node_offset_switch_special_prong: i32, - /// The source location points to all the ranges of a switch expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a switch expression AST node. Next, navigate to any of the - /// range nodes. The error applies to all of them. - /// The Decl is determined contextually. - node_offset_switch_range: i32, - /// The source location points to the capture of a switch_prong. - /// The Decl is determined contextually. - node_offset_switch_prong_capture: i32, - /// The source location points to the tag capture of a switch_prong. - /// The Decl is determined contextually. - node_offset_switch_prong_tag_capture: i32, - /// The source location points to the align expr of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the calling convention node. - /// The Decl is determined contextually. - node_offset_fn_type_align: i32, - /// The source location points to the addrspace expr of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the calling convention node. - /// The Decl is determined contextually. - node_offset_fn_type_addrspace: i32, - /// The source location points to the linksection expr of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the calling convention node. - /// The Decl is determined contextually. - node_offset_fn_type_section: i32, - /// The source location points to the calling convention of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the calling convention node. - /// The Decl is determined contextually. - node_offset_fn_type_cc: i32, - /// The source location points to the return type of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the return type node. - /// The Decl is determined contextually. - node_offset_fn_type_ret_ty: i32, - node_offset_param: i32, - token_offset_param: i32, - /// The source location points to the type expression of an `anyframe->T` - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate - /// to the type expression. - /// The Decl is determined contextually. - node_offset_anyframe_type: i32, - /// The source location points to the string literal of `extern "foo"`, found - /// by taking this AST node index offset from the containing - /// Decl AST node, which points to a function prototype or variable declaration - /// expression AST node. Next, navigate to the string literal of the `extern "foo"`. - /// The Decl is determined contextually. - node_offset_lib_name: i32, - /// The source location points to the len expression of an `[N:S]T` - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate - /// to the len expression. - /// The Decl is determined contextually. - node_offset_array_type_len: i32, - /// The source location points to the sentinel expression of an `[N:S]T` - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_array_type_sentinel: i32, - /// The source location points to the elem expression of an `[N:S]T` - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate - /// to the elem expression. - /// The Decl is determined contextually. - node_offset_array_type_elem: i32, - /// The source location points to the operand of an unary expression. - /// The Decl is determined contextually. - node_offset_un_op: i32, - /// The source location points to the elem type of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_elem: i32, - /// The source location points to the sentinel of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_sentinel: i32, - /// The source location points to the align expr of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_align: i32, - /// The source location points to the addrspace expr of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_addrspace: i32, - /// The source location points to the bit-offset of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_bitoffset: i32, - /// The source location points to the host size of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_hostsize: i32, - /// The source location points to the tag type of an union or an enum. - /// The Decl is determined contextually. - node_offset_container_tag: i32, - /// The source location points to the default value of a field. - /// The Decl is determined contextually. - node_offset_field_default: i32, - /// The source location points to the type of an array or struct initializer. - /// The Decl is determined contextually. - node_offset_init_ty: i32, - /// The source location points to the LHS of an assignment. - /// The Decl is determined contextually. - node_offset_store_ptr: i32, - /// The source location points to the RHS of an assignment. - /// The Decl is determined contextually. - node_offset_store_operand: i32, - /// The source location points to the operand of a `return` statement, or - /// the `return` itself if there is no explicit operand. - /// The Decl is determined contextually. - node_offset_return_operand: i32, - /// The source location points to a for loop input. - /// The Decl is determined contextually. - for_input: struct { - /// Points to the for loop AST node. - for_node_offset: i32, - /// Picks one of the inputs from the condition. - input_index: u32, - }, - /// The source location points to one of the captures of a for loop, found - /// by taking this AST node index offset from the containing - /// Decl AST node, which points to one of the input nodes of a for loop. - /// Next, navigate to the corresponding capture. - /// The Decl is determined contextually. - for_capture_from_input: i32, - /// The source location points to the argument node of a function call. - call_arg: struct { - decl: Decl.Index, - /// Points to the function call AST node. - call_node_offset: i32, - /// The index of the argument the source location points to. - arg_index: u32, - }, - fn_proto_param: struct { - decl: Decl.Index, - /// Points to the function prototype AST node. - fn_proto_node_offset: i32, - /// The index of the parameter the source location points to. - param_index: u32, - }, - array_cat_lhs: ArrayCat, - array_cat_rhs: ArrayCat, +pub const LazySrcLoc = struct { + /// This instruction provides the source node locations are resolved relative to. + /// It is a `declaration`, `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl`. + /// This must be valid even if `relative` is an absolute value, since it is required to + /// determine the file which the `LazySrcLoc` refers to. + base_node_inst: InternPool.TrackedInst.Index, + /// This field determines the source location relative to `base_node_inst`. + offset: Offset, - const ArrayCat = struct { - /// Points to the array concat AST node. - array_cat_offset: i32, - /// The index of the element the source location points to. - elem_index: u32, + pub const Offset = union(enum) { + /// When this tag is set, the code that constructed this `LazySrcLoc` is asserting + /// that all code paths which would need to resolve the source location are + /// unreachable. If you are debugging this tag incorrectly being this value, + /// look into using reverse-continue with a memory watchpoint to see where the + /// value is being set to this tag. + /// `base_node_inst` is unused. + unneeded, + /// Means the source location points to an entire file; not any particular + /// location within the file. `file_scope` union field will be active. + entire_file, + /// The source location points to a byte offset within a source file, + /// offset from 0. The source file is determined contextually. + /// Inside a `SrcLoc`, the `file_scope` union field will be active. + byte_abs: u32, + /// The source location points to a token within a source file, + /// offset from 0. The source file is determined contextually. + /// Inside a `SrcLoc`, the `file_scope` union field will be active. + token_abs: u32, + /// The source location points to an AST node within a source file, + /// offset from 0. The source file is determined contextually. + /// Inside a `SrcLoc`, the `file_scope` union field will be active. + node_abs: u32, + /// The source location points to a byte offset within a source file, + /// offset from the byte offset of the base node within the file. + byte_offset: u32, + /// This data is the offset into the token list from the base node's first token. + token_offset: u32, + /// The source location points to an AST node, which is this value offset + /// from its containing base node AST index. + node_offset: TracedOffset, + /// The source location points to the main token of an AST node, found + /// by taking this AST node index offset from the containing base node. + node_offset_main_token: i32, + /// The source location points to the beginning of a struct initializer. + node_offset_initializer: i32, + /// The source location points to a variable declaration type expression, + /// found by taking this AST node index offset from the containing + /// base node, which points to a variable declaration AST node. Next, navigate + /// to the type expression. + node_offset_var_decl_ty: i32, + /// The source location points to the alignment expression of a var decl. + node_offset_var_decl_align: i32, + /// The source location points to the linksection expression of a var decl. + node_offset_var_decl_section: i32, + /// The source location points to the addrspace expression of a var decl. + node_offset_var_decl_addrspace: i32, + /// The source location points to the initializer of a var decl. + node_offset_var_decl_init: i32, + /// The source location points to the given argument of a builtin function call. + /// `builtin_call_node` points to the builtin call. + /// `arg_index` is the index of the argument which hte source location refers to. + node_offset_builtin_call_arg: struct { + builtin_call_node: i32, + arg_index: u32, + }, + /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls + /// to pointer cast builtins (taking the first argument of the most nested). + node_offset_ptrcast_operand: i32, + /// The source location points to the index expression of an array access + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to an array access AST node. Next, navigate + /// to the index expression. + node_offset_array_access_index: i32, + /// The source location points to the LHS of a slice expression + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a slice AST node. Next, navigate + /// to the sentinel expression. + node_offset_slice_ptr: i32, + /// The source location points to start expression of a slice expression + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a slice AST node. Next, navigate + /// to the sentinel expression. + node_offset_slice_start: i32, + /// The source location points to the end expression of a slice + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a slice AST node. Next, navigate + /// to the sentinel expression. + node_offset_slice_end: i32, + /// The source location points to the sentinel expression of a slice + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a slice AST node. Next, navigate + /// to the sentinel expression. + node_offset_slice_sentinel: i32, + /// The source location points to the callee expression of a function + /// call expression, found by taking this AST node index offset from the containing + /// base node, which points to a function call AST node. Next, navigate + /// to the callee expression. + node_offset_call_func: i32, + /// The payload is offset from the containing base node. + /// The source location points to the field name of: + /// * a field access expression (`a.b`), or + /// * the callee of a method call (`a.b()`) + node_offset_field_name: i32, + /// The payload is offset from the containing base node. + /// The source location points to the field name of the operand ("b" node) + /// of a field initialization expression (`.a = b`) + node_offset_field_name_init: i32, + /// The source location points to the pointer of a pointer deref expression, + /// found by taking this AST node index offset from the containing + /// base node, which points to a pointer deref AST node. Next, navigate + /// to the pointer expression. + node_offset_deref_ptr: i32, + /// The source location points to the assembly source code of an inline assembly + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to inline assembly AST node. Next, navigate + /// to the asm template source code. + node_offset_asm_source: i32, + /// The source location points to the return type of an inline assembly + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to inline assembly AST node. Next, navigate + /// to the return type expression. + node_offset_asm_ret_ty: i32, + /// The source location points to the condition expression of an if + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to an if expression AST node. Next, navigate + /// to the condition expression. + node_offset_if_cond: i32, + /// The source location points to a binary expression, such as `a + b`, found + /// by taking this AST node index offset from the containing base node. + node_offset_bin_op: i32, + /// The source location points to the LHS of a binary expression, found + /// by taking this AST node index offset from the containing base node, + /// which points to a binary expression AST node. Next, navigate to the LHS. + node_offset_bin_lhs: i32, + /// The source location points to the RHS of a binary expression, found + /// by taking this AST node index offset from the containing base node, + /// which points to a binary expression AST node. Next, navigate to the RHS. + node_offset_bin_rhs: i32, + /// The source location points to the operand of a switch expression, found + /// by taking this AST node index offset from the containing base node, + /// which points to a switch expression AST node. Next, navigate to the operand. + node_offset_switch_operand: i32, + /// The source location points to the else/`_` prong of a switch expression, found + /// by taking this AST node index offset from the containing base node, + /// which points to a switch expression AST node. Next, navigate to the else/`_` prong. + node_offset_switch_special_prong: i32, + /// The source location points to all the ranges of a switch expression, found + /// by taking this AST node index offset from the containing base node, + /// which points to a switch expression AST node. Next, navigate to any of the + /// range nodes. The error applies to all of them. + node_offset_switch_range: i32, + /// The source location points to the align expr of a function type + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a function type AST node. Next, navigate to + /// the calling convention node. + node_offset_fn_type_align: i32, + /// The source location points to the addrspace expr of a function type + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a function type AST node. Next, navigate to + /// the calling convention node. + node_offset_fn_type_addrspace: i32, + /// The source location points to the linksection expr of a function type + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a function type AST node. Next, navigate to + /// the calling convention node. + node_offset_fn_type_section: i32, + /// The source location points to the calling convention of a function type + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a function type AST node. Next, navigate to + /// the calling convention node. + node_offset_fn_type_cc: i32, + /// The source location points to the return type of a function type + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a function type AST node. Next, navigate to + /// the return type node. + node_offset_fn_type_ret_ty: i32, + node_offset_param: i32, + token_offset_param: i32, + /// The source location points to the type expression of an `anyframe->T` + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to a `anyframe->T` expression AST node. Next, navigate + /// to the type expression. + node_offset_anyframe_type: i32, + /// The source location points to the string literal of `extern "foo"`, found + /// by taking this AST node index offset from the containing + /// base node, which points to a function prototype or variable declaration + /// expression AST node. Next, navigate to the string literal of the `extern "foo"`. + node_offset_lib_name: i32, + /// The source location points to the len expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the len expression. + node_offset_array_type_len: i32, + /// The source location points to the sentinel expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the sentinel expression. + node_offset_array_type_sentinel: i32, + /// The source location points to the elem expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// base node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the elem expression. + node_offset_array_type_elem: i32, + /// The source location points to the operand of an unary expression. + node_offset_un_op: i32, + /// The source location points to the elem type of a pointer. + node_offset_ptr_elem: i32, + /// The source location points to the sentinel of a pointer. + node_offset_ptr_sentinel: i32, + /// The source location points to the align expr of a pointer. + node_offset_ptr_align: i32, + /// The source location points to the addrspace expr of a pointer. + node_offset_ptr_addrspace: i32, + /// The source location points to the bit-offset of a pointer. + node_offset_ptr_bitoffset: i32, + /// The source location points to the host size of a pointer. + node_offset_ptr_hostsize: i32, + /// The source location points to the tag type of an union or an enum. + node_offset_container_tag: i32, + /// The source location points to the default value of a field. + node_offset_field_default: i32, + /// The source location points to the type of an array or struct initializer. + node_offset_init_ty: i32, + /// The source location points to the LHS of an assignment. + node_offset_store_ptr: i32, + /// The source location points to the RHS of an assignment. + node_offset_store_operand: i32, + /// The source location points to the operand of a `return` statement, or + /// the `return` itself if there is no explicit operand. + node_offset_return_operand: i32, + /// The source location points to a for loop input. + for_input: struct { + /// Points to the for loop AST node. + for_node_offset: i32, + /// Picks one of the inputs from the condition. + input_index: u32, + }, + /// The source location points to one of the captures of a for loop, found + /// by taking this AST node index offset from the containing + /// base node, which points to one of the input nodes of a for loop. + /// Next, navigate to the corresponding capture. + for_capture_from_input: i32, + /// The source location points to the argument node of a function call. + call_arg: struct { + /// Points to the function call AST node. + call_node_offset: i32, + /// The index of the argument the source location points to. + arg_index: u32, + }, + fn_proto_param: FnProtoParam, + fn_proto_param_type: FnProtoParam, + array_cat_lhs: ArrayCat, + array_cat_rhs: ArrayCat, + /// The source location points to the name of the field at the given index + /// of the container type declaration at the base node. + container_field_name: u32, + /// Like `continer_field_name`, but points at the field's default value. + container_field_value: u32, + /// Like `continer_field_name`, but points at the field's type. + container_field_type: u32, + /// Like `continer_field_name`, but points at the field's alignment. + container_field_align: u32, + /// The source location points to the given element/field of a struct or + /// array initialization expression. + init_elem: struct { + /// Points to the AST node of the initialization expression. + init_node_offset: i32, + /// The index of the field/element the source location points to. + elem_index: u32, + }, + // The following source locations are like `init_elem`, but refer to a + // field with a specific name. If such a field is not given, the entire + // initialization expression is used instead. + // The `i32` points to the AST node of a builtin call, whose *second* + // argument is the init expression. + init_field_name: i32, + init_field_linkage: i32, + init_field_section: i32, + init_field_visibility: i32, + init_field_rw: i32, + init_field_locality: i32, + init_field_cache: i32, + init_field_library: i32, + init_field_thread_local: i32, + /// The source location points to the value of an item in a specific + /// case of a `switch`. + switch_case_item: SwitchItem, + /// The source location points to the "first" value of a range item in + /// a specific case of a `switch`. + switch_case_item_range_first: SwitchItem, + /// The source location points to the "last" value of a range item in + /// a specific case of a `switch`. + switch_case_item_range_last: SwitchItem, + /// The source location points to the main capture of a specific case of + /// a `switch`. + switch_capture: SwitchCapture, + /// The source location points to the "tag" capture (second capture) of + /// a specific case of a `switch`. + switch_tag_capture: SwitchCapture, + + pub const FnProtoParam = struct { + /// The offset of the function prototype AST node. + fn_proto_node_offset: i32, + /// The index of the parameter the source location points to. + param_index: u32, + }; + + pub const SwitchItem = struct { + /// The offset of the switch AST node. + switch_node_offset: i32, + /// The index of the case to point to within this switch. + case_idx: SwitchCaseIndex, + /// The index of the item to point to within this case. + item_idx: SwitchItemIndex, + }; + + pub const SwitchCapture = struct { + /// The offset of the switch AST node. + switch_node_offset: i32, + /// The index of the case whose capture to point to. + case_idx: SwitchCaseIndex, + }; + + pub const SwitchCaseIndex = packed struct(u32) { + kind: enum(u1) { scalar, multi }, + index: u31, + + pub const special: SwitchCaseIndex = @bitCast(@as(u32, std.math.maxInt(u32))); + pub fn isSpecial(idx: SwitchCaseIndex) bool { + return @as(u32, @bitCast(idx)) == @as(u32, @bitCast(special)); + } + }; + + pub const SwitchItemIndex = packed struct(u32) { + kind: enum(u1) { single, range }, + index: u31, + }; + + const ArrayCat = struct { + /// Points to the array concat AST node. + array_cat_offset: i32, + /// The index of the element the source location points to. + elem_index: u32, + }; + + pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; + + noinline fn nodeOffsetDebug(node_offset: i32) Offset { + var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; + result.node_offset.trace.addAddr(@returnAddress(), "init"); + return result; + } + + fn nodeOffsetRelease(node_offset: i32) Offset { + return .{ .node_offset = .{ .x = node_offset } }; + } + + /// This wraps a simple integer in debug builds so that later on we can find out + /// where in semantic analysis the value got set. + pub const TracedOffset = struct { + x: i32, + trace: std.debug.Trace = std.debug.Trace.init, + + const want_tracing = false; + }; }; - pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; - - noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc { - var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; - result.node_offset.trace.addAddr(@returnAddress(), "init"); - return result; - } - - fn nodeOffsetRelease(node_offset: i32) LazySrcLoc { - return .{ .node_offset = .{ .x = node_offset } }; - } - - /// This wraps a simple integer in debug builds so that later on we can find out - /// where in semantic analysis the value got set. - pub const TracedOffset = struct { - x: i32, - trace: std.debug.Trace = std.debug.Trace.init, - - const want_tracing = false; + pub const unneeded: LazySrcLoc = .{ + .base_node_inst = undefined, + .offset = .unneeded, }; + + pub fn resolveBaseNode(base_node_inst: InternPool.TrackedInst.Index, zcu: *Zcu) struct { *File, Ast.Node.Index } { + const want_path_digest, const zir_inst = inst: { + const info = base_node_inst.resolveFull(&zcu.intern_pool); + break :inst .{ info.path_digest, info.inst }; + }; + // TODO: avoid iterating all files for this! + const file = for (zcu.import_table.values()) |file| { + if (std.mem.eql(u8, &file.path_digest, &want_path_digest)) break file; + } else unreachable; + assert(file.zir_loaded); + + const zir = file.zir; + const inst = zir.instructions.get(@intFromEnum(zir_inst)); + const base_node: Ast.Node.Index = switch (inst.tag) { + .declaration => inst.data.declaration.src_node, + .extended => switch (inst.data.extended.opcode) { + .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_node, + .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node, + .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node, + .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node, + else => unreachable, + }, + else => unreachable, + }; + return .{ file, base_node }; + } + + /// Resolve the file and AST node of `base_node_inst` to get a resolved `SrcLoc`. + /// TODO: it is incorrect to store a `SrcLoc` anywhere due to incremental compilation. + /// Probably the type should be removed entirely and this resolution performed on-the-fly when needed. + pub fn upgrade(lazy: LazySrcLoc, zcu: *Zcu) SrcLoc { + const file, const base_node = resolveBaseNode(lazy.base_node_inst, zcu); + return .{ + .file_scope = file, + .base_node = base_node, + .lazy = lazy.offset, + }; + } }; pub const SemaError = error{ OutOfMemory, AnalysisFail }; @@ -2260,11 +2397,6 @@ pub const CompileError = error{ OutOfMemory, /// When this is returned, the compile error for the failure has already been recorded. AnalysisFail, - /// Returned when a compile error needed to be reported but a provided LazySrcLoc was set - /// to the `unneeded` tag. The source location was, in fact, needed. It is expected that - /// somewhere up the call stack, the operation will be retried after doing expensive work - /// to compute a source location. - NeededSourceLocation, /// A Type or Value was needed to be used during semantic analysis, but it was not available /// because the function is generic. This is only seen when analyzing the body of a param /// instruction. @@ -3373,7 +3505,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { } return error.AnalysisFail; }, - error.NeededSourceLocation => unreachable, error.GenericPoison => unreachable, else => |e| { decl.analysis = .sema_failure; @@ -3381,7 +3512,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { try mod.retryable_failures.append(mod.gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( mod.gpa, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), "unable to analyze: {s}", .{@errorName(e)}, )); @@ -3555,7 +3686,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In decl_index, try Module.ErrorMsg.create( gpa, - decl.srcLoc(zcu), + decl.navSrcLoc(zcu).upgrade(zcu), "invalid liveness: {s}", .{@errorName(err)}, ), @@ -3579,7 +3710,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( gpa, - decl.srcLoc(zcu), + decl.navSrcLoc(zcu).upgrade(zcu), "unable to codegen: {s}", .{@errorName(err)}, )); @@ -3814,7 +3945,7 @@ fn semaFile(mod: *Module, file: *File) SemaError!void { }); errdefer mod.destroyNamespace(new_namespace_index); - const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0); + const new_decl_index = try mod.allocateNewDecl(new_namespace_index); const new_decl = mod.declPtr(new_decl_index); errdefer @panic("TODO error handling"); @@ -3961,7 +4092,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { var analysis_arena = std.heap.ArenaAllocator.init(gpa); defer analysis_arena.deinit(); - var comptime_err_ret_trace = std.ArrayList(SrcLoc).init(gpa); + var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); defer comptime_err_ret_trace.deinit(); var sema: Sema = .{ @@ -3996,6 +4127,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = decl.zir_decl_index.unwrap().?, }; defer block_scope.instructions.deinit(gpa); @@ -4005,11 +4137,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { // We'll do some other bits with the Sema. Clear the type target index just // in case they analyze any type. sema.builtin_type_target_index = .none; - const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 }; - const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 }; - const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 }; - const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; - const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; + const align_src: LazySrcLoc = block_scope.src(.{ .node_offset_var_decl_align = 0 }); + const section_src: LazySrcLoc = block_scope.src(.{ .node_offset_var_decl_section = 0 }); + const address_space_src: LazySrcLoc = block_scope.src(.{ .node_offset_var_decl_addrspace = 0 }); + const ty_src: LazySrcLoc = block_scope.src(.{ .node_offset_var_decl_ty = 0 }); + const init_src: LazySrcLoc = block_scope.src(.{ .node_offset_var_decl_init = 0 }); const decl_val = try sema.resolveFinalDeclValue(&block_scope, init_src, result_ref); const decl_ty = decl_val.typeOf(mod); @@ -4143,7 +4275,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { } if (decl.is_exported) { - const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) }; + const export_src: LazySrcLoc = block_scope.src(.{ .token_offset = @intFromBool(decl.is_pub) }); if (is_inline) return sema.fail(&block_scope, export_src, "export of inline function", .{}); // The scope needs to have the decl in it. try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); @@ -4697,14 +4829,13 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void const was_exported = decl.is_exported; assert(decl.kind == kind); // ZIR tracking should preserve this decl.name = decl_name; - decl.src_node = inst_data.src_node; decl.src_line = line; decl.is_pub = declaration.flags.is_pub; decl.is_exported = declaration.flags.is_export; break :decl_index .{ was_exported, decl_index }; } else decl_index: { // Create and set up a new Decl. - const new_decl_index = try zcu.allocateNewDecl(namespace_index, inst_data.src_node); + const new_decl_index = try zcu.allocateNewDecl(namespace_index); const new_decl = zcu.declPtr(new_decl_index); new_decl.kind = kind; new_decl.name = decl_name; @@ -4858,7 +4989,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.Depender.wrap(.{ .func = func_index })); - var comptime_err_ret_trace = std.ArrayList(SrcLoc).init(gpa); + var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); defer comptime_err_ret_trace.deinit(); // In the case of a generic function instance, this is the type of the @@ -4913,6 +5044,14 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato .instructions = .{}, .inlining = null, .is_comptime = false, + .src_base_inst = inst: { + const owner_info = if (func.generic_owner == .none) + func + else + mod.funcInfo(func.generic_owner); + const orig_decl = mod.declPtr(owner_info.owner_decl); + break :inst orig_decl.zir_decl_index.unwrap().?; + }, }; defer inner_block.instructions.deinit(gpa); @@ -4954,7 +5093,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato runtime_param_index += 1; const opt_opv = sema.typeHasOnePossibleValue(Type.fromInterned(param_ty)) catch |err| switch (err) { - error.NeededSourceLocation => unreachable, error.GenericPoison => unreachable, error.ComptimeReturn => unreachable, error.ComptimeBreak => unreachable, @@ -4988,7 +5126,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) { // TODO make these unreachable instead of @panic - error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"), error.GenericPoison => @panic("zig compiler bug: GenericPoison"), error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"), else => |e| return e, @@ -5010,7 +5147,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato { sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) { // TODO make these unreachable instead of @panic - error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"), error.GenericPoison => @panic("zig compiler bug: GenericPoison"), error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"), error.ComptimeBreak => @panic("zig compiler bug: ComptimeBreak"), @@ -5031,8 +5167,10 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato // state to success, so that "unable to resolve inferred error set" errors // can be emitted here. if (sema.fn_ret_ty_ies) |ies| { - sema.resolveInferredErrorSetPtr(&inner_block, LazySrcLoc.nodeOffset(0), ies) catch |err| switch (err) { - error.NeededSourceLocation => unreachable, + sema.resolveInferredErrorSetPtr(&inner_block, .{ + .base_node_inst = inner_block.src_base_inst, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }, ies) catch |err| switch (err) { error.GenericPoison => unreachable, error.ComptimeReturn => unreachable, error.ComptimeBreak => unreachable, @@ -5056,7 +5194,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato // so that dependencies on the function body will now be satisfied rather than // result in circular dependency errors. sema.resolveFnTypes(fn_ty) catch |err| switch (err) { - error.NeededSourceLocation => unreachable, error.GenericPoison => unreachable, error.ComptimeReturn => unreachable, error.ComptimeBreak => unreachable, @@ -5073,7 +5210,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato // the backends. for (sema.types_to_resolve.keys()) |ty| { sema.resolveTypeFully(Type.fromInterned(ty)) catch |err| switch (err) { - error.NeededSourceLocation => unreachable, error.GenericPoison => unreachable, error.ComptimeReturn => unreachable, error.ComptimeBreak => unreachable, @@ -5101,17 +5237,11 @@ pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void { return mod.intern_pool.destroyNamespace(mod.gpa, index); } -pub fn allocateNewDecl( - mod: *Module, - namespace: Namespace.Index, - src_node: Ast.Node.Index, -) !Decl.Index { - const ip = &mod.intern_pool; - const gpa = mod.gpa; - const decl_index = try ip.createDecl(gpa, .{ +pub fn allocateNewDecl(zcu: *Zcu, namespace: Namespace.Index) !Decl.Index { + const gpa = zcu.gpa; + const decl_index = try zcu.intern_pool.createDecl(gpa, .{ .name = undefined, .src_namespace = namespace, - .src_node = src_node, .src_line = undefined, .has_tv = false, .owns_tv = false, @@ -5126,10 +5256,10 @@ pub fn allocateNewDecl( .kind = .anon, }); - if (mod.emit_h) |mod_emit_h| { - if (@intFromEnum(decl_index) >= mod_emit_h.allocated_emit_h.len) { - try mod_emit_h.allocated_emit_h.append(gpa, .{}); - assert(@intFromEnum(decl_index) == mod_emit_h.allocated_emit_h.len); + if (zcu.emit_h) |zcu_emit_h| { + if (@intFromEnum(decl_index) >= zcu_emit_h.allocated_emit_h.len) { + try zcu_emit_h.allocated_emit_h.append(gpa, .{}); + assert(@intFromEnum(decl_index) == zcu_emit_h.allocated_emit_h.len); } } @@ -5223,376 +5353,6 @@ fn lockAndClearFileCompileError(mod: *Module, file: *File) void { } } -pub const SwitchProngSrc = union(enum) { - /// The item for a scalar prong. - scalar: u32, - /// A given single item for a multi prong. - multi: Multi, - /// A given range item for a multi prong. - range: Multi, - /// The item for the special prong. - special, - /// The main capture for a scalar prong. - scalar_capture: u32, - /// The main capture for a multi prong. - multi_capture: u32, - /// The main capture for the special prong. - special_capture, - /// The tag capture for a scalar prong. - scalar_tag_capture: u32, - /// The tag capture for a multi prong. - multi_tag_capture: u32, - /// The tag capture for the special prong. - special_tag_capture, - - pub const Multi = struct { - prong: u32, - item: u32, - }; - - pub const RangeExpand = enum { none, first, last }; - - /// This function is intended to be called only when it is certain that we need - /// the LazySrcLoc in order to emit a compile error. - pub fn resolve( - prong_src: SwitchProngSrc, - mod: *Module, - decl: *Decl, - switch_node_offset: i32, - /// Ignored if `prong_src` is not `.range` - range_expand: RangeExpand, - ) LazySrcLoc { - @setCold(true); - const gpa = mod.gpa; - const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { - // In this case we emit a warning + a less precise source location. - log.warn("unable to load {s}: {s}", .{ - decl.getFileScope(mod).sub_file_path, @errorName(err), - }); - return LazySrcLoc.nodeOffset(0); - }; - const switch_node = decl.relativeToNodeIndex(switch_node_offset); - const main_tokens = tree.nodes.items(.main_token); - const node_datas = tree.nodes.items(.data); - const node_tags = tree.nodes.items(.tag); - const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); - const case_nodes = tree.extra_data[extra.start..extra.end]; - - var multi_i: u32 = 0; - var scalar_i: u32 = 0; - const case_node = for (case_nodes) |case_node| { - const case = tree.fullSwitchCase(case_node).?; - - const is_special = special: { - if (case.ast.values.len == 0) break :special true; - if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) { - break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"); - } - break :special false; - }; - - if (is_special) { - switch (prong_src) { - .special, .special_capture, .special_tag_capture => break case_node, - else => continue, - } - } - - const is_multi = case.ast.values.len != 1 or - node_tags[case.ast.values[0]] == .switch_range; - - switch (prong_src) { - .scalar, - .scalar_capture, - .scalar_tag_capture, - => |i| if (!is_multi and i == scalar_i) break case_node, - - .multi_capture, - .multi_tag_capture, - => |i| if (is_multi and i == multi_i) break case_node, - - .multi, - .range, - => |m| if (is_multi and m.prong == multi_i) break case_node, - - .special, - .special_capture, - .special_tag_capture, - => {}, - } - - if (is_multi) { - multi_i += 1; - } else { - scalar_i += 1; - } - } else unreachable; - - const case = tree.fullSwitchCase(case_node).?; - - switch (prong_src) { - .scalar, .special => return LazySrcLoc.nodeOffset( - decl.nodeIndexToRelative(case.ast.values[0]), - ), - .multi => |m| { - var item_i: u32 = 0; - for (case.ast.values) |item_node| { - if (node_tags[item_node] == .switch_range) continue; - if (item_i == m.item) return LazySrcLoc.nodeOffset( - decl.nodeIndexToRelative(item_node), - ); - item_i += 1; - } - unreachable; - }, - .range => |m| { - var range_i: u32 = 0; - for (case.ast.values) |range| { - if (node_tags[range] != .switch_range) continue; - if (range_i == m.item) switch (range_expand) { - .none => return LazySrcLoc.nodeOffset( - decl.nodeIndexToRelative(range), - ), - .first => return LazySrcLoc.nodeOffset( - decl.nodeIndexToRelative(node_datas[range].lhs), - ), - .last => return LazySrcLoc.nodeOffset( - decl.nodeIndexToRelative(node_datas[range].rhs), - ), - }; - range_i += 1; - } - unreachable; - }, - .scalar_capture, .multi_capture, .special_capture => { - return .{ .node_offset_switch_prong_capture = decl.nodeIndexToRelative(case_node) }; - }, - .scalar_tag_capture, .multi_tag_capture, .special_tag_capture => { - return .{ .node_offset_switch_prong_tag_capture = decl.nodeIndexToRelative(case_node) }; - }, - } - } -}; - -pub const PeerTypeCandidateSrc = union(enum) { - /// Do not print out error notes for candidate sources - none: void, - /// When we want to know the the src of candidate i, look up at - /// index i in this slice - override: []const ?LazySrcLoc, - /// resolvePeerTypes originates from a @TypeOf(...) call - typeof_builtin_call_node_offset: i32, - - pub fn resolve( - self: PeerTypeCandidateSrc, - mod: *Module, - decl: *Decl, - candidate_i: usize, - ) ?LazySrcLoc { - @setCold(true); - const gpa = mod.gpa; - - switch (self) { - .none => { - return null; - }, - .override => |candidate_srcs| { - if (candidate_i >= candidate_srcs.len) - return null; - return candidate_srcs[candidate_i]; - }, - .typeof_builtin_call_node_offset => |node_offset| { - switch (candidate_i) { - 0 => return LazySrcLoc{ .node_offset_builtin_call_arg0 = node_offset }, - 1 => return LazySrcLoc{ .node_offset_builtin_call_arg1 = node_offset }, - 2 => return LazySrcLoc{ .node_offset_builtin_call_arg2 = node_offset }, - 3 => return LazySrcLoc{ .node_offset_builtin_call_arg3 = node_offset }, - 4 => return LazySrcLoc{ .node_offset_builtin_call_arg4 = node_offset }, - 5 => return LazySrcLoc{ .node_offset_builtin_call_arg5 = node_offset }, - else => {}, - } - - const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { - // In this case we emit a warning + a less precise source location. - log.warn("unable to load {s}: {s}", .{ - decl.getFileScope(mod).sub_file_path, @errorName(err), - }); - return LazySrcLoc.nodeOffset(0); - }; - const node = decl.relativeToNodeIndex(node_offset); - const node_datas = tree.nodes.items(.data); - const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; - - return LazySrcLoc{ .node_abs = params[candidate_i] }; - }, - } - } -}; - -const FieldSrcQuery = struct { - index: usize, - range: enum { name, type, value, alignment } = .name, -}; - -fn queryFieldSrc( - tree: Ast, - query: FieldSrcQuery, - file_scope: *File, - container_decl: Ast.full.ContainerDecl, -) SrcLoc { - var field_index: usize = 0; - for (container_decl.ast.members) |member_node| { - const field = tree.fullContainerField(member_node) orelse continue; - if (field_index == query.index) { - return switch (query.range) { - .name => .{ - .file_scope = file_scope, - .parent_decl_node = 0, - .lazy = .{ .token_abs = field.ast.main_token }, - }, - .type => .{ - .file_scope = file_scope, - .parent_decl_node = 0, - .lazy = .{ .node_abs = field.ast.type_expr }, - }, - .value => .{ - .file_scope = file_scope, - .parent_decl_node = 0, - .lazy = .{ .node_abs = field.ast.value_expr }, - }, - .alignment => .{ - .file_scope = file_scope, - .parent_decl_node = 0, - .lazy = .{ .node_abs = field.ast.align_expr }, - }, - }; - } - field_index += 1; - } - unreachable; -} - -pub fn paramSrc( - func_node_offset: i32, - mod: *Module, - decl: *Decl, - param_i: usize, -) LazySrcLoc { - @setCold(true); - const gpa = mod.gpa; - const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { - // In this case we emit a warning + a less precise source location. - log.warn("unable to load {s}: {s}", .{ - decl.getFileScope(mod).sub_file_path, @errorName(err), - }); - return LazySrcLoc.nodeOffset(0); - }; - const node = decl.relativeToNodeIndex(func_node_offset); - var buf: [1]Ast.Node.Index = undefined; - const full = tree.fullFnProto(&buf, node).?; - var it = full.iterate(tree); - var i: usize = 0; - while (it.next()) |param| : (i += 1) { - if (i == param_i) { - if (param.anytype_ellipsis3) |some| { - const main_token = tree.nodes.items(.main_token)[decl.src_node]; - return .{ .token_offset_param = @as(i32, @bitCast(some)) - @as(i32, @bitCast(main_token)) }; - } - return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) }; - } - } - unreachable; -} - -pub fn initSrc( - mod: *Module, - init_node_offset: i32, - decl: *Decl, - init_index: usize, -) LazySrcLoc { - @setCold(true); - const gpa = mod.gpa; - const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { - // In this case we emit a warning + a less precise source location. - log.warn("unable to load {s}: {s}", .{ - decl.getFileScope(mod).sub_file_path, @errorName(err), - }); - return LazySrcLoc.nodeOffset(0); - }; - const node_tags = tree.nodes.items(.tag); - const node = decl.relativeToNodeIndex(init_node_offset); - var buf: [2]Ast.Node.Index = undefined; - switch (node_tags[node]) { - .array_init_one, - .array_init_one_comma, - .array_init_dot_two, - .array_init_dot_two_comma, - .array_init_dot, - .array_init_dot_comma, - .array_init, - .array_init_comma, - => { - const full = tree.fullArrayInit(&buf, node).?.ast.elements; - return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full[init_index])); - }, - .struct_init_one, - .struct_init_one_comma, - .struct_init_dot_two, - .struct_init_dot_two_comma, - .struct_init_dot, - .struct_init_dot_comma, - .struct_init, - .struct_init_comma, - => { - const full = tree.fullStructInit(&buf, node).?.ast.fields; - return LazySrcLoc{ .node_offset_initializer = decl.nodeIndexToRelative(full[init_index]) }; - }, - else => return LazySrcLoc.nodeOffset(init_node_offset), - } -} - -pub fn optionsSrc(mod: *Module, decl: *Decl, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc { - @setCold(true); - const gpa = mod.gpa; - const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { - // In this case we emit a warning + a less precise source location. - log.warn("unable to load {s}: {s}", .{ - decl.getFileScope(mod).sub_file_path, @errorName(err), - }); - return LazySrcLoc.nodeOffset(0); - }; - - const o_i: struct { off: i32, i: u8 } = switch (base_src) { - .node_offset_builtin_call_arg0 => |n| .{ .off = n, .i = 0 }, - .node_offset_builtin_call_arg1 => |n| .{ .off = n, .i = 1 }, - else => unreachable, - }; - - const node = decl.relativeToNodeIndex(o_i.off); - const node_datas = tree.nodes.items(.data); - const node_tags = tree.nodes.items(.tag); - const arg_node = switch (node_tags[node]) { - .builtin_call_two, .builtin_call_two_comma => switch (o_i.i) { - 0 => node_datas[node].lhs, - 1 => node_datas[node].rhs, - else => unreachable, - }, - .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + o_i.i], - else => unreachable, - }; - var buf: [2]std.zig.Ast.Node.Index = undefined; - const init_nodes = if (tree.fullStructInit(&buf, arg_node)) |struct_init| struct_init.ast.fields else return base_src; - for (init_nodes) |init_node| { - // . IDENTIFIER = init_node - const name_token = tree.firstToken(init_node) - 2; - const name = tree.tokenSlice(name_token); - if (std.mem.eql(u8, name, wanted)) { - return LazySrcLoc{ .node_offset_initializer = decl.nodeIndexToRelative(init_node) }; - } - } - return base_src; -} - /// Called from `Compilation.update`, after everything is done, just before /// reporting compile errors. In this function we emit exported symbol collision /// errors and communicate exported symbols to the linker backend. @@ -5826,7 +5586,7 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void { try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( gpa, - decl.srcLoc(zcu), + decl.navSrcLoc(zcu).upgrade(zcu), "unable to codegen: {s}", .{@errorName(err)}, )); @@ -5857,7 +5617,7 @@ fn reportRetryableFileError( mod.gpa, .{ .file_scope = file, - .parent_decl_node = 0, + .base_node = 0, .lazy = .entire_file, }, format, @@ -6432,27 +6192,6 @@ pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func return mod.intern_pool.indexToKey(func_index).func; } -pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc { - @setCold(true); - const owner_decl = mod.declPtr(owner_decl_index); - const file = owner_decl.getFileScope(mod); - const tree = file.getTree(mod.gpa) catch |err| { - // In this case we emit a warning + a less precise source location. - log.warn("unable to load {s}: {s}", .{ - file.sub_file_path, @errorName(err), - }); - return owner_decl.srcLoc(mod); - }; - const node = owner_decl.relativeToNodeIndex(0); - var buf: [2]Ast.Node.Index = undefined; - if (tree.fullContainerDecl(&buf, node)) |container_decl| { - return queryFieldSrc(tree.*, query, file, container_decl); - } else { - // This type was generated using @Type - return owner_decl.srcLoc(mod); - } -} - pub fn toEnum(mod: *Module, comptime E: type, val: Value) E { return mod.intern_pool.toEnum(E, val.toIntern()); } diff --git a/src/RangeSet.zig b/src/RangeSet.zig index 00dc257d1a..4e2eaa633a 100644 --- a/src/RangeSet.zig +++ b/src/RangeSet.zig @@ -7,7 +7,7 @@ const Type = @import("type.zig").Type; const Value = @import("Value.zig"); const Module = @import("Module.zig"); const RangeSet = @This(); -const SwitchProngSrc = @import("Module.zig").SwitchProngSrc; +const LazySrcLoc = @import("Module.zig").LazySrcLoc; ranges: std.ArrayList(Range), module: *Module, @@ -15,7 +15,7 @@ module: *Module, pub const Range = struct { first: InternPool.Index, last: InternPool.Index, - src: SwitchProngSrc, + src: LazySrcLoc, }; pub fn init(allocator: std.mem.Allocator, module: *Module) RangeSet { @@ -33,8 +33,8 @@ pub fn add( self: *RangeSet, first: InternPool.Index, last: InternPool.Index, - src: SwitchProngSrc, -) !?SwitchProngSrc { + src: LazySrcLoc, +) !?LazySrcLoc { const mod = self.module; const ip = &mod.intern_pool; diff --git a/src/Sema.zig b/src/Sema.zig index eacc4e097d..aa4d459f1b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -34,7 +34,7 @@ func_index: InternPool.Index, func_is_naked: bool, /// Used to restore the error return trace when returning a non-error from a function. error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, -comptime_err_ret_trace: *std.ArrayList(Module.SrcLoc), +comptime_err_ret_trace: *std.ArrayList(LazySrcLoc), /// When semantic analysis needs to know the return type of the function whose body /// is being analyzed, this `Type` should be used instead of going through `func`. /// This will correctly handle the case of a comptime/inline function call of a @@ -65,9 +65,7 @@ generic_owner: InternPool.Index = .none, /// instantiation callsite so that compile errors on the parameter types of the /// instantiation can point back to the instantiation site in addition to the /// declaration site. -generic_call_src: LazySrcLoc = .unneeded, -/// Corresponds to `generic_call_src`. -generic_call_decl: InternPool.OptionalDeclIndex = .none, +generic_call_src: LazySrcLoc = LazySrcLoc.unneeded, /// The key is types that must be fully resolved prior to machine code /// generation pass. Types are added to this set when resolving them /// immediately could cause a dependency loop, but they do need to be resolved @@ -131,7 +129,6 @@ const MaybeComptimeAlloc = struct { /// If the instruction is one of these three tags, `src` may be `.unneeded`. stores: std.MultiArrayList(struct { inst: Air.Inst.Index, - src_decl: InternPool.DeclIndex, src: LazySrcLoc, }) = .{}, }; @@ -361,8 +358,8 @@ pub const Block = struct { label: ?*Label = null, inlining: ?*Inlining, /// If runtime_index is not 0 then one of these is guaranteed to be non null. - runtime_cond: ?Module.SrcLoc = null, - runtime_loop: ?Module.SrcLoc = null, + runtime_cond: ?LazySrcLoc = null, + runtime_loop: ?LazySrcLoc = null, /// This Decl is the Decl according to the Zig source code corresponding to this Block. /// This can vary during inline or comptime function calls. See `Sema.owner_decl` /// for the one that will be the same for all Block instances. @@ -395,25 +392,39 @@ pub const Block = struct { /// `block` in order for codegen to match lexical scoping for debug vars. need_debug_scope: ?*bool = null, - // These functions will be less stupid soon! + /// Relative source locations encountered while traversing this block should be + /// treated as relative to the AST node of this ZIR instruction. + src_base_inst: InternPool.TrackedInst.Index, + + /// Create a `LazySrcLoc` based on an `Offset` from the code being analyzed in this block. + /// Specifically, the given `Offset` is treated as relative to `block.src_base_inst`. + pub fn src(block: Block, offset: LazySrcLoc.Offset) LazySrcLoc { + return .{ + .base_node_inst = block.src_base_inst, + .offset = offset, + }; + } + + fn builtinCallArgSrc(block: *Block, builtin_call_node: i32, arg_index: u32) LazySrcLoc { + return block.src(.{ .node_offset_builtin_call_arg = .{ + .builtin_call_node = builtin_call_node, + .arg_index = arg_index, + } }); + } fn nodeOffset(block: Block, node_offset: i32) LazySrcLoc { - _ = block; - return LazySrcLoc.nodeOffset(node_offset); + return block.src(LazySrcLoc.Offset.nodeOffset(node_offset)); } fn tokenOffset(block: Block, tok_offset: u32) LazySrcLoc { - _ = block; - return .{ .token_offset = tok_offset }; + return block.src(.{ .token_offset = tok_offset }); } const ComptimeReason = union(enum) { c_import: struct { - block: *Block, src: LazySrcLoc, }, comptime_ret_ty: struct { - block: *Block, func: Air.Inst.Ref, func_src: LazySrcLoc, return_ty: Type, @@ -425,27 +436,23 @@ pub const Block = struct { const prefix = "expression is evaluated at comptime because "; switch (cr) { .c_import => |ci| { - try sema.errNote(ci.block, ci.src, parent, prefix ++ "it is inside a @cImport", .{}); + try sema.errNote(ci.src, parent, prefix ++ "it is inside a @cImport", .{}); }, .comptime_ret_ty => |rt| { - const src_loc = if (try sema.funcDeclSrc(rt.func)) |fn_decl| blk: { - var src_loc = fn_decl.srcLoc(mod); - src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 }; - break :blk src_loc; - } else blk: { - const src_decl = mod.declPtr(rt.block.src_decl); - break :blk src_decl.toSrcLoc(rt.func_src, mod); - }; + const ret_ty_src: LazySrcLoc = if (try sema.funcDeclSrc(rt.func)) |fn_decl| .{ + .base_node_inst = fn_decl.zir_decl_index.unwrap().?, + .offset = .{ .node_offset_fn_type_ret_ty = 0 }, + } else rt.func_src; if (rt.return_ty.isGenericPoison()) { - return mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{}); + return sema.errNote(ret_ty_src, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{}); } - try mod.errNoteNonLazy( - src_loc, + try sema.errNote( + ret_ty_src, parent, prefix ++ "the function returns a comptime-only type '{}'", .{rt.return_ty.fmt(mod)}, ); - try sema.explainWhyTypeIsComptime(parent, src_loc, rt.return_ty); + try sema.explainWhyTypeIsComptime(parent, ret_ty_src, rt.return_ty); }, } } @@ -525,6 +532,7 @@ pub const Block = struct { .c_import_buf = parent.c_import_buf, .error_return_trace_index = parent.error_return_trace_index, .need_debug_scope = parent.need_debug_scope, + .src_base_inst = parent.src_base_inst, }; } @@ -815,14 +823,6 @@ pub const Block = struct { return result_index; } - fn addUnreachable(block: *Block, src: LazySrcLoc, safety_check: bool) !void { - if (safety_check and block.wantSafety()) { - try block.sema.safetyPanic(block, src, .unreach); - } else { - _ = try block.addNoOp(.unreach); - } - } - pub fn ownerModule(block: Block) *Package.Module { const zcu = block.sema.mod; return zcu.namespacePtr(block.namespace).file_scope.mod; @@ -1237,7 +1237,7 @@ fn analyzeBodyInner( .@"asm" => try sema.zirAsm( block, extended, false), .asm_expr => try sema.zirAsm( block, extended, true), .typeof_peer => try sema.zirTypeofPeer( block, extended, inst), - .compile_log => try sema.zirCompileLog( extended), + .compile_log => try sema.zirCompileLog( block, extended), .min_multi => try sema.zirMinMaxMulti( block, extended, .min), .max_multi => try sema.zirMinMaxMulti( block, extended, .max), .add_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), @@ -1475,10 +1475,9 @@ fn analyzeBodyInner( if (@intFromEnum(target_runtime_index) < @intFromEnum(block.runtime_index)) { const runtime_src = block.runtime_cond orelse block.runtime_loop.?; const msg = msg: { - const msg = try sema.errMsg(block, src, "comptime control flow inside runtime block", .{}); + const msg = try sema.errMsg(src, "comptime control flow inside runtime block", .{}); errdefer msg.destroy(sema.gpa); - - try mod.errNoteNonLazy(runtime_src, msg, "runtime control flow here", .{}); + try sema.errNote(runtime_src, msg, "runtime control flow here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -1522,7 +1521,7 @@ fn analyzeBodyInner( .repeat => { if (block.is_comptime) { // Send comptime control flow back to the beginning of this block. - const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); + const src = block.nodeOffset(datas[@intFromEnum(inst)].node); try sema.emitBackwardBranch(block, src); i = 0; continue; @@ -1535,7 +1534,7 @@ fn analyzeBodyInner( }, .repeat_inline => { // Send comptime control flow back to the beginning of this block. - const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); + const src = block.nodeOffset(datas[@intFromEnum(inst)].node); try sema.emitBackwardBranch(block, src); i = 0; continue; @@ -1705,7 +1704,7 @@ fn analyzeBodyInner( } // Same as condbr_inline. TODO https://github.com/ziglang/zig/issues/8220 const inst_data = datas[@intFromEnum(inst)].pl_node; - const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node }; + const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len); const else_body = sema.code.bodySlice( @@ -1725,7 +1724,7 @@ fn analyzeBodyInner( }, .condbr_inline => blk: { const inst_data = datas[@intFromEnum(inst)].pl_node; - const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node }; + const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len); const else_body = sema.code.bodySlice( @@ -1749,7 +1748,7 @@ fn analyzeBodyInner( if (!block.is_comptime) break :blk try sema.zirTry(block, inst); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; + const operand_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); const err_union = try sema.resolveInst(extra.data.operand); @@ -1775,7 +1774,7 @@ fn analyzeBodyInner( if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; + const operand_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); const operand = try sema.resolveInst(extra.data.operand); @@ -1939,14 +1938,14 @@ fn resolveDestType( // Cast builtins use their result type as the destination type, but // it could be an anytype argument, which we can't catch in AstGen. const msg = msg: { - const msg = try sema.errMsg(block, src, "{s} must have a known result type", .{builtin_name}); + const msg = try sema.errMsg(src, "{s} must have a known result type", .{builtin_name}); errdefer msg.destroy(sema.gpa); switch (sema.genericPoisonReason(block, zir_ref)) { - .anytype_param => |call_src| try sema.errNote(block, call_src, msg, "result type is unknown due to anytype parameter", .{}), - .anyopaque_ptr => |ptr_src| try sema.errNote(block, ptr_src, msg, "result type is unknown due to opaque pointer type", .{}), + .anytype_param => |call_src| try sema.errNote(call_src, msg, "result type is unknown due to anytype parameter", .{}), + .anyopaque_ptr => |ptr_src| try sema.errNote(ptr_src, msg, "result type is unknown due to opaque pointer type", .{}), .unknown => {}, } - try sema.errNote(block, src, msg, "use @as to provide explicit result type", .{}); + try sema.errNote(src, msg, "use @as to provide explicit result type", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -2051,7 +2050,7 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) var err_trace_block = block.makeSubBlock(); defer err_trace_block.instructions.deinit(gpa); - const src: LazySrcLoc = .unneeded; + const src: LazySrcLoc = LazySrcLoc.unneeded; // var addrs: [err_return_trace_addr_count]usize = undefined; const err_return_trace_addr_count = 32; @@ -2212,9 +2211,9 @@ pub fn resolveFinalDeclValue( fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: NeededComptimeReason) CompileError { const msg = msg: { - const msg = try sema.errMsg(block, src, "unable to resolve comptime value", .{}); + const msg = try sema.errMsg(src, "unable to resolve comptime value", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "{s}", .{reason.needed_comptime_reason}); + try sema.errNote(src, msg, "{s}", .{reason.needed_comptime_reason}); if (reason.block_comptime_reason) |block_comptime_reason| { try block_comptime_reason.explain(sema, msg); @@ -2241,12 +2240,12 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError { const mod = sema.mod; const msg = msg: { - const msg = try sema.errMsg(block, src, "expected optional type, found '{}'", .{ + const msg = try sema.errMsg(src, "expected optional type, found '{}'", .{ non_optional_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); if (non_optional_ty.zigTypeTag(mod) == .ErrorUnion) { - try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{}); + try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); } try addDeclaredHereNote(sema, msg, non_optional_ty); break :msg msg; @@ -2257,12 +2256,12 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { const mod = sema.mod; const msg = msg: { - const msg = try sema.errMsg(block, src, "type '{}' does not support array initialization syntax", .{ + const msg = try sema.errMsg(src, "type '{}' does not support array initialization syntax", .{ ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); if (ty.isSlice(mod)) { - try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(mod).fmt(mod)}); + try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(mod).fmt(mod)}); } break :msg msg; }; @@ -2291,11 +2290,11 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: const zcu = sema.mod; if (int_ty.zigTypeTag(zcu) == .Vector) { const msg = msg: { - const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{ + const msg = try sema.errMsg(src, "overflow of vector type '{}' with value '{}'", .{ int_ty.fmt(zcu), val.fmtValue(zcu, sema), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "when computing vector element at index '{d}'", .{vector_index}); + try sema.errNote(src, msg, "when computing vector element at index '{d}'", .{vector_index}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -2308,15 +2307,14 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError { const mod = sema.mod; const msg = msg: { - const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{}); + const msg = try sema.errMsg(init_src, "value stored in comptime field does not match the default value of the field", .{}); errdefer msg.destroy(sema.gpa); const struct_type = mod.typeToStruct(container_ty) orelse break :msg msg; - const default_value_src = mod.fieldSrcLoc(struct_type.decl.unwrap().?, .{ - .index = field_index, - .range = .value, - }); - try mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{}); + try sema.errNote(.{ + .base_node_inst = struct_type.zir_index.unwrap().?, + .offset = .{ .container_field_value = @intCast(field_index) }, + }, msg, "default value set here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -2324,7 +2322,7 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { const msg = msg: { - const msg = try sema.errMsg(block, src, "async has not been implemented in the self-hosted compiler yet", .{}); + const msg = try sema.errMsg(src, "async has not been implemented in the self-hosted compiler yet", .{}); errdefer msg.destroy(sema.gpa); break :msg msg; }; @@ -2345,9 +2343,9 @@ fn failWithInvalidFieldAccess( const child_ty = inner_ty.optionalChild(mod); if (!typeSupportsFieldAccess(mod, child_ty, field_name)) break :opt; const msg = msg: { - const msg = try sema.errMsg(block, src, "optional type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(src, "optional type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "consider using '.?', 'orelse', or 'if'", .{}); + try sema.errNote(src, msg, "consider using '.?', 'orelse', or 'if'", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -2355,9 +2353,9 @@ fn failWithInvalidFieldAccess( const child_ty = inner_ty.errorUnionPayload(mod); if (!typeSupportsFieldAccess(mod, child_ty, field_name)) break :err; const msg = msg: { - const msg = try sema.errMsg(block, src, "error union type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(src, "error union type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{}); + try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -2390,11 +2388,11 @@ fn failWithComptimeErrorRetTrace( ) CompileError { const mod = sema.mod; const msg = msg: { - const msg = try sema.errMsg(block, src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)}); + const msg = try sema.errMsg(src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)}); errdefer msg.destroy(sema.gpa); for (sema.comptime_err_ret_trace.items) |src_loc| { - try mod.errNoteNonLazy(src_loc, msg, "error returned here", .{}); + try sema.errNote(src_loc, msg, "error returned here", .{}); } break :msg msg; }; @@ -2403,17 +2401,15 @@ fn failWithComptimeErrorRetTrace( /// We don't return a pointer to the new error note because the pointer /// becomes invalid when you add another one. -fn errNote( +pub fn errNote( sema: *Sema, - block: *Block, src: LazySrcLoc, parent: *Module.ErrorMsg, comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const mod = sema.mod; - const src_decl = mod.declPtr(block.src_decl); - return mod.errNoteNonLazy(src_decl.toSrcLoc(src, mod), parent, format, args); + const zcu = sema.mod; + return zcu.errNoteNonLazy(src.upgrade(zcu), parent, format, args); } fn addFieldErrNote( @@ -2425,52 +2421,23 @@ fn addFieldErrNote( args: anytype, ) !void { @setCold(true); - const mod = sema.mod; - const decl_index = container_ty.getOwnerDecl(mod); - const decl = mod.declPtr(decl_index); - - const field_src = blk: { - const tree = decl.getFileScope(mod).getTree(sema.gpa) catch |err| { - log.err("unable to load AST to report compile error: {s}", .{@errorName(err)}); - break :blk decl.srcLoc(mod); - }; - - const container_node = decl.relativeToNodeIndex(0); - const node_tags = tree.nodes.items(.tag); - var buf: [2]std.zig.Ast.Node.Index = undefined; - const container_decl = tree.fullContainerDecl(&buf, container_node) orelse break :blk decl.srcLoc(mod); - - var it_index: usize = 0; - for (container_decl.ast.members) |member_node| { - switch (node_tags[member_node]) { - .container_field_init, - .container_field_align, - .container_field, - => { - if (it_index == field_index) { - break :blk decl.nodeOffsetSrcLoc(decl.nodeIndexToRelative(member_node), mod); - } - it_index += 1; - }, - else => continue, - } - } - unreachable; + const zcu = sema.mod; + const type_src = container_ty.srcLocOrNull(zcu) orelse return; + const field_src: LazySrcLoc = .{ + .base_node_inst = type_src.base_node_inst, + .offset = .{ .container_field_name = @intCast(field_index) }, }; - try mod.errNoteNonLazy(field_src, parent, format, args); + try sema.errNote(field_src, parent, format, args); } pub fn errMsg( sema: *Sema, - block: *Block, src: LazySrcLoc, comptime format: []const u8, args: anytype, -) error{ NeededSourceLocation, OutOfMemory }!*Module.ErrorMsg { - const mod = sema.mod; - if (src == .unneeded) return error.NeededSourceLocation; - const src_decl = mod.declPtr(block.src_decl); - return Module.ErrorMsg.create(sema.gpa, src_decl.toSrcLoc(src, mod), format, args); +) Allocator.Error!*Module.ErrorMsg { + assert(src.offset != .unneeded); + return Module.ErrorMsg.create(sema.gpa, src.upgrade(sema.mod), format, args); } pub fn fail( @@ -2480,7 +2447,7 @@ pub fn fail( comptime format: []const u8, args: anytype, ) CompileError { - const err_msg = try sema.errMsg(block, src, format, args); + const err_msg = try sema.errMsg(src, format, args); inline for (args) |arg| { if (@TypeOf(arg) == Type.Formatter) { try addDeclaredHereNote(sema, err_msg, arg.data.ty); @@ -2514,7 +2481,6 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error var block_it = start_block; while (block_it.inlining) |inlining| { try sema.errNote( - inlining.call_block, inlining.call_src, err_msg, "called from here", @@ -2548,7 +2514,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error const decl = mod.declPtr(ref.referencer); try reference_stack.append(.{ .decl = decl.name, - .src_loc = decl.toSrcLoc(ref.src, mod), + .src_loc = ref.src.upgrade(mod), }); } referenced_by = ref.referencer; @@ -2583,15 +2549,13 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error /// Reference trace is preserved. fn reparentOwnedErrorMsg( sema: *Sema, - block: *Block, src: LazySrcLoc, msg: *Module.ErrorMsg, comptime format: []const u8, args: anytype, ) !void { const mod = sema.mod; - const src_decl = mod.declPtr(block.src_decl); - const resolved_src = src_decl.toSrcLoc(src, mod); + const resolved_src = src.upgrade(mod); const msg_str = try std.fmt.allocPrint(mod.gpa, format, args); const orig_notes = msg.notes.len; @@ -2728,7 +2692,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us sema.code.nullTerminatedString(str), .no_embedded_nulls, ); - const decl = try sema.lookupIdentifier(block, .unneeded, decl_name); // TODO: could we need this src loc? + const decl = try sema.lookupIdentifier(block, LazySrcLoc.unneeded, decl_name); // TODO: could we need this src loc? break :capture InternPool.CaptureValue.wrap(.{ .decl_val = decl }); }, .decl_ref => |str| capture: { @@ -2737,7 +2701,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us sema.code.nullTerminatedString(str), .no_embedded_nulls, ); - const decl = try sema.lookupIdentifier(block, .unneeded, decl_name); // TODO: could we need this src loc? + const decl = try sema.lookupIdentifier(block, LazySrcLoc.unneeded, decl_name); // TODO: could we need this src loc? break :capture InternPool.CaptureValue.wrap(.{ .decl_ref = decl }); }, }; @@ -2788,7 +2752,13 @@ fn zirStructDecl( const ip = &mod.intern_pool; const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand); - const src: LazySrcLoc = .{ .node_abs = extra.data.src_node }; + + const tracked_inst = try ip.trackZir(gpa, block.getFileScope(mod), inst); + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }; + var extra_index = extra.end; const captures_len = if (small.has_captures_len) blk: { @@ -2832,7 +2802,7 @@ fn zirStructDecl( .any_aligned_fields = small.any_aligned_fields, .has_namespace = true or decls_len > 0, // TODO: see below .key = .{ .declared = .{ - .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), + .zir_index = tracked_inst, .captures = captures, } }, }; @@ -2847,7 +2817,6 @@ fn zirStructDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - extra.data.src_node, Value.fromInterned(wip_ty.index), small.name_strategy, "struct", @@ -2884,7 +2853,6 @@ fn zirStructDecl( fn createAnonymousDeclTypeNamed( sema: *Sema, block: *Block, - src_node: std.zig.Ast.Node.Index, val: Value, name_strategy: Zir.Inst.NameStrategy, anon_prefix: []const u8, @@ -2895,7 +2863,7 @@ fn createAnonymousDeclTypeNamed( const gpa = sema.gpa; const namespace = block.namespace; const src_decl = zcu.declPtr(block.src_decl); - const new_decl_index = try zcu.allocateNewDecl(namespace, src_node); + const new_decl_index = try zcu.allocateNewDecl(namespace); errdefer zcu.destroyDecl(new_decl_index); switch (name_strategy) { @@ -2924,8 +2892,7 @@ fn createAnonymousDeclTypeNamed( // If not then this is a struct type being returned from a non-generic // function and the name doesn't matter since it will later // result in a compile error. - const arg_val = sema.resolveConstValue(block, .unneeded, arg, undefined) catch - break :func_strat; // fall through to anon strat + const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat if (arg_i != 0) try writer.writeByte(','); @@ -3003,7 +2970,9 @@ fn zirEnumDecl( const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand); var extra_index: usize = extra.end; - const src: LazySrcLoc = .{ .node_abs = extra.data.src_node }; + const tracked_inst = try ip.trackZir(gpa, block.getFileScope(mod), inst); + const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) }; + const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } }; const tag_type_ref = if (small.has_tag_type) blk: { const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); @@ -3063,7 +3032,7 @@ fn zirEnumDecl( .explicit, .fields_len = fields_len, .key = .{ .declared = .{ - .zir_index = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst), + .zir_index = tracked_inst, .captures = captures, } }, }; @@ -3083,7 +3052,6 @@ fn zirEnumDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - extra.data.src_node, Value.fromInterned(wip_ty.index), small.name_strategy, "enum", @@ -3149,12 +3117,10 @@ fn zirEnumDecl( .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = tracked_inst, }; defer enum_block.instructions.deinit(sema.gpa); - // This source location applies in the context of `enum_block`. - const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = 0 }; - if (body.len != 0) { _ = try sema.analyzeInlineBody(&enum_block, body, inst); } @@ -3199,36 +3165,33 @@ fn zirEnumDecl( const field_name = try mod.intern_pool.getOrPutString(gpa, field_name_zir, .no_embedded_nulls); + const value_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .container_field_value = field_i }, + }; + const tag_overflow = if (has_tag_value) overflow: { const tag_val_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); extra_index += 1; const tag_inst = try sema.resolveInst(tag_val_ref); - last_tag_val = sema.resolveConstDefinedValue(block, .unneeded, tag_inst, undefined) catch |err| switch (err) { - error.NeededSourceLocation => { - const value_src = mod.fieldSrcLoc(new_decl_index, .{ - .index = field_i, - .range = .value, - }).lazy; - _ = try sema.resolveConstDefinedValue(block, value_src, tag_inst, .{ - .needed_comptime_reason = "enum tag value must be comptime-known", - }); - unreachable; - }, - else => |e| return e, - }; + last_tag_val = try sema.resolveConstDefinedValue(block, .{ + .base_node_inst = tracked_inst, + .offset = .{ .container_field_name = field_i }, + }, tag_inst, .{ + .needed_comptime_reason = "enum tag value must be comptime-known", + }); if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true; last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty); if (wip_ty.nextField(&mod.intern_pool, field_name, last_tag_val.?.toIntern())) |conflict| { assert(conflict.kind == .value); // AstGen validated names are unique - const value_src = mod.fieldSrcLoc(new_decl_index, .{ - .index = field_i, - .range = .value, - }).lazy; - const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy; + const other_field_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .container_field_value = conflict.prev_field_idx }, + }; const msg = msg: { - const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(sema.mod, sema)}); + const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(sema.mod, sema)}); errdefer msg.destroy(gpa); - try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); + try sema.errNote(other_field_src, msg, "other occurrence here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -3243,12 +3206,14 @@ fn zirEnumDecl( if (overflow != null) break :overflow true; if (wip_ty.nextField(&mod.intern_pool, field_name, last_tag_val.?.toIntern())) |conflict| { assert(conflict.kind == .value); // AstGen validated names are unique - const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy; - const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy; + const other_field_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .container_field_value = conflict.prev_field_idx }, + }; const msg = msg: { - const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(sema.mod, sema)}); + const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(sema.mod, sema)}); errdefer msg.destroy(gpa); - try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); + try sema.errNote(other_field_src, msg, "other occurrence here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -3263,11 +3228,7 @@ fn zirEnumDecl( }; if (tag_overflow) { - const value_src = mod.fieldSrcLoc(new_decl_index, .{ - .index = field_i, - .range = if (has_tag_value) .value else .name, - }).lazy; - const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{ + const msg = try sema.errMsg(value_src, "enumeration value '{}' too large for type '{}'", .{ last_tag_val.?.fmtValue(mod, sema), int_tag_ty.fmt(mod), }); return sema.failWithOwnedErrorMsg(block, msg); @@ -3294,7 +3255,8 @@ fn zirUnionDecl( const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand); var extra_index: usize = extra.end; - const src: LazySrcLoc = .{ .node_abs = extra.data.src_node }; + const tracked_inst = try ip.trackZir(gpa, block.getFileScope(mod), inst); + const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) }; extra_index += @intFromBool(small.has_tag_type); const captures_len = if (small.has_captures_len) blk: { @@ -3342,7 +3304,7 @@ fn zirUnionDecl( .field_types = &.{}, // set later .field_aligns = &.{}, // set later .key = .{ .declared = .{ - .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), + .zir_index = tracked_inst, .captures = captures, } }, }; @@ -3357,7 +3319,6 @@ fn zirUnionDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - extra.data.src_node, Value.fromInterned(wip_ty.index), small.name_strategy, "union", @@ -3409,7 +3370,8 @@ fn zirOpaqueDecl( const extra = sema.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); var extra_index: usize = extra.end; - const src: LazySrcLoc = .{ .node_abs = extra.data.src_node }; + const tracked_inst = try ip.trackZir(gpa, block.getFileScope(mod), inst); + const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) }; const captures_len = if (small.has_captures_len) blk: { const captures_len = sema.code.extra[extra_index]; @@ -3429,7 +3391,7 @@ fn zirOpaqueDecl( const opaque_init: InternPool.OpaqueTypeInit = .{ .has_namespace = decls_len != 0, .key = .{ .declared = .{ - .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), + .zir_index = tracked_inst, .captures = captures, } }, }; @@ -3445,7 +3407,6 @@ fn zirOpaqueDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - extra.data.src_node, Value.fromInterned(wip_ty.index), small.name_strategy, "opaque", @@ -3566,19 +3527,19 @@ fn ensureResultUsed( .ErrorSet => return sema.fail(block, src, "error set is ignored", .{}), .ErrorUnion => { const msg = msg: { - const msg = try sema.errMsg(block, src, "error union is ignored", .{}); + const msg = try sema.errMsg(src, "error union is ignored", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{}); + try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); }, else => { const msg = msg: { - const msg = try sema.errMsg(block, src, "value of type '{}' ignored", .{ty.fmt(sema.mod)}); + const msg = try sema.errMsg(src, "value of type '{}' ignored", .{ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "all non-void values must be used", .{}); - try sema.errNote(block, src, msg, "to discard the value, assign it to '_'", .{}); + try sema.errNote(src, msg, "all non-void values must be used", .{}); + try sema.errNote(src, msg, "to discard the value, assign it to '_'", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -3599,9 +3560,9 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com .ErrorSet => return sema.fail(block, src, "error set is discarded", .{}), .ErrorUnion => { const msg = msg: { - const msg = try sema.errMsg(block, src, "error union is discarded", .{}); + const msg = try sema.errMsg(src, "error union is discarded", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{}); + try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -3627,9 +3588,9 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index const payload_ty = err_union_ty.errorUnionPayload(mod).zigTypeTag(mod); if (payload_ty != .Void and payload_ty != .NoReturn) { const msg = msg: { - const msg = try sema.errMsg(block, src, "error union payload is ignored", .{}); + const msg = try sema.errMsg(src, "error union payload is ignored", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "payload value can be explicitly ignored with '|_|'", .{}); + try sema.errNote(src, msg, "payload value can be explicitly ignored with '|_|'", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -3683,8 +3644,8 @@ fn zirAllocExtended( ) CompileError!Air.Inst.Ref { const gpa = sema.gpa; const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); - const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = extra.data.src_node }; - const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = extra.data.src_node }; + const ty_src = block.src(.{ .node_offset_var_decl_ty = extra.data.src_node }); + const align_src = block.src(.{ .node_offset_var_decl_align = extra.data.src_node }); const small: Zir.Inst.AllocExtended.Small = @bitCast(extended.small); var extra_index: usize = extra.end; @@ -3760,7 +3721,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; + const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); return sema.analyzeComptimeAlloc(block, var_ty, .none); } @@ -3826,7 +3787,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro if (try sema.typeRequiresComptime(elem_ty)) { // The value was initialized through RLS, so we didn't detect the runtime condition earlier. // TODO: source location of runtime control flow - const init_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const init_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); return sema.fail(block, init_src, "value with comptime-only type '{}' depends on runtime control flow", .{elem_ty.fmt(mod)}); } @@ -3995,7 +3956,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, .ty = opt_ty.toIntern(), .val = payload_val.toIntern(), } }); - try sema.storePtrVal(block, .unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(opt_val), opt_ty); + try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(opt_val), opt_ty); break :ptr (try Value.fromInterned(decl_parent_ptr).ptrOptPayload(sema)).toIntern(); }, .eu_payload => ptr: { @@ -4008,7 +3969,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, .ty = eu_ty.toIntern(), .val = .{ .payload = payload_val.toIntern() }, } }); - try sema.storePtrVal(block, .unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(eu_val), eu_ty); + try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(eu_val), eu_ty); break :ptr (try Value.fromInterned(decl_parent_ptr).ptrEuPayload(sema)).toIntern(); }, .field => |idx| ptr: { @@ -4021,7 +3982,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try zcu.undefValue(payload_ty); const tag_val = try zcu.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), idx); const store_val = try zcu.unionValue(maybe_union_ty, tag_val, payload_val); - try sema.storePtrVal(block, .unneeded, Value.fromInterned(decl_parent_ptr), store_val, maybe_union_ty); + try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), store_val, maybe_union_ty); } break :ptr (try Value.fromInterned(decl_parent_ptr).ptrField(idx, sema)).toIntern(); }, @@ -4043,14 +4004,14 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, const air_ptr_inst = store_inst.data.bin_op.lhs.toIndex().?; const store_val = (try sema.resolveValue(store_inst.data.bin_op.rhs)).?; const new_ptr = ptr_mapping.get(air_ptr_inst).?; - try sema.storePtrVal(block, .unneeded, Value.fromInterned(new_ptr), store_val, Type.fromInterned(zcu.intern_pool.typeOf(store_val.toIntern()))); + try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(new_ptr), store_val, Type.fromInterned(zcu.intern_pool.typeOf(store_val.toIntern()))); }, else => unreachable, } } // The value is finalized - load it! - const val = (try sema.pointerDeref(block, .unneeded, Value.fromInterned(alloc_ptr), alloc_ty)).?.toIntern(); + const val = (try sema.pointerDeref(block, LazySrcLoc.unneeded, Value.fromInterned(alloc_ptr), alloc_ty)).?.toIntern(); return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, ct_alloc, alloc_inst, comptime_info.value); } @@ -4153,7 +4114,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; + const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); if (block.is_comptime) { return sema.analyzeComptimeAlloc(block, var_ty, .none); @@ -4176,7 +4137,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; + const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); if (block.is_comptime) { return sema.analyzeComptimeAlloc(block, var_ty, .none); @@ -4236,7 +4197,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com const gpa = sema.gpa; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; + const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const ptr = try sema.resolveInst(inst_data.operand); const ptr_inst = ptr.toIndex().?; const target = mod.getTarget(); @@ -4399,20 +4360,20 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. .Int, .ComptimeInt => true, else => false, }; - const arg_src: LazySrcLoc = .{ .for_input = .{ + const arg_src = block.src(.{ .for_input = .{ .for_node_offset = inst_data.src_node, .input_index = i, - } }; + } }); const arg_len_uncoerced = if (is_int) object else l: { if (!object_ty.isIndexable(mod)) { // Instead of using checkIndexable we customize this error. const msg = msg: { - const msg = try sema.errMsg(block, arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{}); + try sema.errNote(arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{}); if (object_ty.zigTypeTag(mod) == .ErrorUnion) { - try sema.errNote(block, arg_src, msg, "consider using 'try', 'catch', or 'if'", .{}); + try sema.errNote(arg_src, msg, "consider using 'try', 'catch', or 'if'", .{}); } break :msg msg; @@ -4432,16 +4393,16 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. if (len_val) |v| { if (!(try sema.valuesEqual(arg_val, v, Type.usize))) { const msg = msg: { - const msg = try sema.errMsg(block, src, "non-matching for loop lengths", .{}); + const msg = try sema.errMsg(src, "non-matching for loop lengths", .{}); errdefer msg.destroy(gpa); - const a_src: LazySrcLoc = .{ .for_input = .{ + const a_src = block.src(.{ .for_input = .{ .for_node_offset = inst_data.src_node, .input_index = len_idx, - } }; - try sema.errNote(block, a_src, msg, "length {} here", .{ + } }); + try sema.errNote(a_src, msg, "length {} here", .{ v.fmtValue(sema.mod, sema), }); - try sema.errNote(block, arg_src, msg, "length {} here", .{ + try sema.errNote(arg_src, msg, "length {} here", .{ arg_val.fmtValue(sema.mod, sema), }); break :msg msg; @@ -4461,7 +4422,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. if (len == .none) { const msg = msg: { - const msg = try sema.errMsg(block, src, "unbounded for loop", .{}); + const msg = try sema.errMsg(src, "unbounded for loop", .{}); errdefer msg.destroy(gpa); for (args, 0..) |zir_arg, i_usize| { const i: u32 = @intCast(i_usize); @@ -4474,11 +4435,11 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. .Int, .ComptimeInt => continue, else => {}, } - const arg_src: LazySrcLoc = .{ .for_input = .{ + const arg_src = block.src(.{ .for_input = .{ .for_node_offset = inst_data.src_node, .input_index = i, - } }; - try sema.errNote(block, arg_src, msg, "type '{}' has no upper bound", .{ + } }); + try sema.errNote(arg_src, msg, "type '{}' has no upper bound", .{ object_ty.fmt(sema.mod), }); } @@ -4528,7 +4489,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const src = block.nodeOffset(pl_node.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; const uncoerced_val = try sema.resolveInst(extra.rhs); - const maybe_wrapped_ptr_ty = sema.resolveType(block, .unneeded, extra.lhs) catch |err| switch (err) { + const maybe_wrapped_ptr_ty = sema.resolveType(block, LazySrcLoc.unneeded, extra.lhs) catch |err| switch (err) { error.GenericPoison => return uncoerced_val, else => |e| return e, }; @@ -4590,9 +4551,9 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr if (ty_operand.isGenericPoison()) return; if (ty_operand.optEuBaseType(mod).zigTypeTag(mod) != .Pointer) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "expected type '{}', found pointer", .{ty_operand.fmt(mod)}); + const msg = try sema.errMsg(src, "expected type '{}', found pointer", .{ty_operand.fmt(mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "address-of operator always returns a pointer", .{}); + try sema.errNote(src, msg, "address-of operator always returns a pointer", .{}); break :msg msg; }); } @@ -4607,7 +4568,7 @@ fn zirValidateArrayInitRefTy( const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(pl_node.src_node); const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data; - const maybe_wrapped_ptr_ty = sema.resolveType(block, .unneeded, extra.ptr_ty) catch |err| switch (err) { + const maybe_wrapped_ptr_ty = sema.resolveType(block, LazySrcLoc.unneeded, extra.ptr_ty) catch |err| switch (err) { error.GenericPoison => return .generic_poison_type, else => |e| return e, }; @@ -4648,7 +4609,7 @@ fn zirValidateArrayInitTy( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const ty_src: LazySrcLoc = if (is_result_ty) src else .{ .node_offset_init_ty = inst_data.src_node }; + const ty_src: LazySrcLoc = if (is_result_ty) src else block.src(.{ .node_offset_init_ty = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; const ty = sema.resolveType(block, ty_src, extra.ty) catch |err| switch (err) { // It's okay for the type to be unknown: this will result in an anonymous array init. @@ -4774,7 +4735,6 @@ fn validateUnionInit( if (instrs.len != 1) { const msg = msg: { const msg = try sema.errMsg( - block, init_src, "cannot initialize multiple union fields at once; unions can only have one active field", .{}, @@ -4783,8 +4743,8 @@ fn validateUnionInit( for (instrs[1..]) |inst| { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const inst_src: LazySrcLoc = .{ .node_offset_initializer = inst_data.src_node }; - try sema.errNote(block, inst_src, msg, "additional initializer here", .{}); + const inst_src = block.src(.{ .node_offset_initializer = inst_data.src_node }); + try sema.errNote(inst_src, msg, "additional initializer here", .{}); } try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; @@ -4801,7 +4761,7 @@ fn validateUnionInit( const field_ptr = instrs[0]; const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(field_ptr)].pl_node; - const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node }; + const field_src = block.src(.{ .node_offset_initializer = field_ptr_data.src_node }); const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; const field_name = try mod.intern_pool.getOrPutString( gpa, @@ -4918,7 +4878,7 @@ fn validateUnionInit( const new_tag = Air.internedToRef(tag_val.toIntern()); const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, new_tag); - try sema.checkComptimeKnownStore(block, set_tag_inst, .unneeded); // `unneeded` since this isn't a "proper" store + try sema.checkComptimeKnownStore(block, set_tag_inst, LazySrcLoc.unneeded); // `unneeded` since this isn't a "proper" store } fn validateStructInit( @@ -4944,7 +4904,7 @@ fn validateStructInit( for (instrs, field_indices) |field_ptr, *field_index| { const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(field_ptr)].pl_node; - const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node }; + const field_src = block.src(.{ .node_offset_initializer = field_ptr_data.src_node }); const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; struct_ptr_zir_ref = field_ptr_extra.lhs; const field_name = try ip.getOrPutString( @@ -4981,18 +4941,18 @@ fn validateStructInit( const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, .{i}); + try sema.errNote(init_src, msg, template, .{i}); } else { - root_msg = try sema.errMsg(block, init_src, template, .{i}); + root_msg = try sema.errMsg(init_src, template, .{i}); } continue; }; const template = "missing struct field: {}"; const args = .{field_name.fmt(ip)}; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, args); + try sema.errNote(init_src, msg, template, args); } else { - root_msg = try sema.errMsg(block, init_src, template, args); + root_msg = try sema.errMsg(init_src, template, args); } continue; } @@ -5007,16 +4967,7 @@ fn validateStructInit( } if (root_msg) |msg| { - if (mod.typeToStruct(struct_ty)) |struct_type| { - const decl = mod.declPtr(struct_type.decl.unwrap().?); - const fqn = try decl.fullyQualifiedName(mod); - try mod.errNoteNonLazy( - decl.srcLoc(mod), - msg, - "struct '{}' declared here", - .{fqn.fmt(ip)}, - ); - } + try sema.addDeclaredHereNote(msg, struct_ty); root_msg = null; return sema.failWithOwnedErrorMsg(block, msg); } @@ -5118,18 +5069,18 @@ fn validateStructInit( const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, .{i}); + try sema.errNote(init_src, msg, template, .{i}); } else { - root_msg = try sema.errMsg(block, init_src, template, .{i}); + root_msg = try sema.errMsg(init_src, template, .{i}); } continue; }; const template = "missing struct field: {}"; const args = .{field_name.fmt(ip)}; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, args); + try sema.errNote(init_src, msg, template, args); } else { - root_msg = try sema.errMsg(block, init_src, template, args); + root_msg = try sema.errMsg(init_src, template, args); } continue; } @@ -5137,21 +5088,12 @@ fn validateStructInit( } if (!struct_is_comptime and !fields_allow_runtime and root_msg == null) { - root_msg = try sema.errMsg(block, init_src, "runtime value contains reference to comptime var", .{}); - try sema.errNote(block, init_src, root_msg.?, "comptime var pointers are not available at runtime", .{}); + root_msg = try sema.errMsg(init_src, "runtime value contains reference to comptime var", .{}); + try sema.errNote(init_src, root_msg.?, "comptime var pointers are not available at runtime", .{}); } if (root_msg) |msg| { - if (mod.typeToStruct(struct_ty)) |struct_type| { - const decl = mod.declPtr(struct_type.decl.unwrap().?); - const fqn = try decl.fullyQualifiedName(mod); - try mod.errNoteNonLazy( - decl.srcLoc(mod), - msg, - "struct '{}' declared here", - .{fqn.fmt(ip)}, - ); - } + try sema.addDeclaredHereNote(msg, struct_ty); root_msg = null; return sema.failWithOwnedErrorMsg(block, msg); } @@ -5253,9 +5195,9 @@ fn zirValidatePtrArrayInit( if (default_val == .unreachable_value) { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, .{i}); + try sema.errNote(init_src, msg, template, .{i}); } else { - root_msg = try sema.errMsg(block, init_src, template, .{i}); + root_msg = try sema.errMsg(init_src, template, .{i}); } continue; } @@ -5455,15 +5397,13 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr } else if (try sema.typeRequiresComptime(elem_ty)) { const msg = msg: { const msg = try sema.errMsg( - block, src, "values of type '{}' must be comptime-known, but operand value is runtime-known", .{elem_ty.fmt(mod)}, ); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(src, mod), elem_ty); + try sema.explainWhyTypeIsComptime(msg, src, elem_ty); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -5475,7 +5415,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const destructure_src = LazySrcLoc.nodeOffset(extra.destructure_node); + const destructure_src = block.nodeOffset(extra.destructure_node); const operand = try sema.resolveInst(extra.operand); const operand_ty = sema.typeOf(operand); @@ -5487,21 +5427,21 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp if (!can_destructure) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "type '{}' cannot be destructured", .{operand_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "type '{}' cannot be destructured", .{operand_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, destructure_src, msg, "result destructured here", .{}); + try sema.errNote(destructure_src, msg, "result destructured here", .{}); break :msg msg; }); } if (operand_ty.arrayLen(mod) != extra.expect_len) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "expected {} elements for destructure, found {}", .{ + const msg = try sema.errMsg(src, "expected {} elements for destructure, found {}", .{ extra.expect_len, operand_ty.arrayLen(mod), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, destructure_src, msg, "result destructured here", .{}); + try sema.errNote(destructure_src, msg, "result destructured here", .{}); break :msg msg; }); } @@ -5536,24 +5476,24 @@ fn failWithBadMemberAccess( fn failWithBadStructFieldAccess( sema: *Sema, block: *Block, + struct_ty: Type, struct_type: InternPool.LoadedStructType, field_src: LazySrcLoc, field_name: InternPool.NullTerminatedString, ) CompileError { - const mod = sema.mod; + const zcu = sema.mod; const gpa = sema.gpa; - const decl = mod.declPtr(struct_type.decl.unwrap().?); - const fqn = try decl.fullyQualifiedName(mod); + const decl = zcu.declPtr(struct_type.decl.unwrap().?); + const fqn = try decl.fullyQualifiedName(zcu); const msg = msg: { const msg = try sema.errMsg( - block, field_src, "no field named '{}' in struct '{}'", - .{ field_name.fmt(&mod.intern_pool), fqn.fmt(&mod.intern_pool) }, + .{ field_name.fmt(&zcu.intern_pool), fqn.fmt(&zcu.intern_pool) }, ); errdefer msg.destroy(gpa); - try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "struct declared here", .{}); + try sema.errNote(struct_ty.srcLoc(zcu), msg, "struct declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -5562,25 +5502,25 @@ fn failWithBadStructFieldAccess( fn failWithBadUnionFieldAccess( sema: *Sema, block: *Block, + union_ty: Type, union_obj: InternPool.LoadedUnionType, field_src: LazySrcLoc, field_name: InternPool.NullTerminatedString, ) CompileError { - const mod = sema.mod; + const zcu = sema.mod; const gpa = sema.gpa; - const decl = mod.declPtr(union_obj.decl); - const fqn = try decl.fullyQualifiedName(mod); + const decl = zcu.declPtr(union_obj.decl); + const fqn = try decl.fullyQualifiedName(zcu); const msg = msg: { const msg = try sema.errMsg( - block, field_src, "no field named '{}' in union '{}'", - .{ field_name.fmt(&mod.intern_pool), fqn.fmt(&mod.intern_pool) }, + .{ field_name.fmt(&zcu.intern_pool), fqn.fmt(&zcu.intern_pool) }, ); errdefer msg.destroy(gpa); - try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "union declared here", .{}); + try sema.errNote(union_ty.srcLoc(zcu), msg, "union declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -5588,16 +5528,15 @@ fn failWithBadUnionFieldAccess( fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void { const mod = sema.mod; - const src_loc = decl_ty.declSrcLocOrNull(mod) orelse return; + const src_loc = decl_ty.srcLocOrNull(mod) orelse return; const category = switch (decl_ty.zigTypeTag(mod)) { .Union => "union", .Struct => "struct", .Enum => "enum", .Opaque => "opaque", - .ErrorSet => "error set", else => unreachable, }; - try mod.errNoteNonLazy(src_loc, parent, "{s} declared here", .{category}); + try sema.errNote(src_loc, parent, "{s} declared here", .{category}); } fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { @@ -5722,8 +5661,8 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v else => {}, }; - const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node }; - const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node }; + const ptr_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); + const operand_src = block.src(.{ .node_offset_store_operand = inst_data.src_node }); const air_tag: Air.Inst.Tag = if (is_ret) .ret_ptr else if (block.wantSafety()) @@ -5837,7 +5776,7 @@ fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const msg = try sema.resolveConstString(block, operand_src, inst_data.operand, .{ .needed_comptime_reason = "compile error string must be comptime-known", }); @@ -5846,6 +5785,7 @@ fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro fn zirCompileLog( sema: *Sema, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const mod = sema.mod; @@ -5878,9 +5818,10 @@ fn zirCompileLog( else sema.owner_decl_index; const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index); - if (!gop.found_existing) { - gop.value_ptr.* = src_node; - } + if (!gop.found_existing) gop.value_ptr.* = .{ + .base_node_inst = block.src_base_inst, + .node_offset = src_node, + }; return .void_value; } @@ -5891,7 +5832,7 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void // `panicWithMsg` would perform this coercion for us, but we can get a better // source location if we do it here. - const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, .{ .node_offset_builtin_call_arg0 = inst_data.src_node }); + const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0)); if (block.is_comptime) { return sema.fail(block, src, "encountered @panic at comptime", .{}); @@ -5901,7 +5842,7 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const src_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].node; - const src = LazySrcLoc.nodeOffset(src_node); + const src = block.nodeOffset(src_node); if (block.is_comptime) return sema.fail(block, src, "encountered @trap at comptime", .{}); _ = try block.addNoOp(.trap); @@ -5948,7 +5889,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError var child_block = parent_block.makeSubBlock(); child_block.label = &label; child_block.runtime_cond = null; - child_block.runtime_loop = mod.declPtr(child_block.src_decl).toSrcLoc(src, mod); + child_block.runtime_loop = src; child_block.runtime_index.increment(); const merges = &child_block.label.?.merges; @@ -5997,10 +5938,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr var c_import_buf = std.ArrayList(u8).init(gpa); defer c_import_buf.deinit(); - var comptime_reason: Block.ComptimeReason = .{ .c_import = .{ - .block = parent_block, - .src = src, - } }; + const comptime_reason: Block.ComptimeReason = .{ .c_import = .{ .src = src } }; var child_block: Block = .{ .parent = parent_block, .sema = sema, @@ -6014,6 +5952,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr .runtime_cond = parent_block.runtime_cond, .runtime_loop = parent_block.runtime_loop, .runtime_index = parent_block.runtime_index, + .src_base_inst = parent_block.src_base_inst, }; defer child_block.instructions.deinit(gpa); @@ -6025,11 +5964,11 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr if (c_import_res.errors.errorMessageCount() != 0) { const msg = msg: { - const msg = try sema.errMsg(&child_block, src, "C import failed", .{}); + const msg = try sema.errMsg(src, "C import failed", .{}); errdefer msg.destroy(gpa); if (!comp.config.link_libc) - try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{}); + try sema.errNote(src, msg, "libc headers not available; compilation does not link against libc", .{}); const gop = try mod.cimport_errors.getOrPut(gpa, sema.owner_decl_index); if (!gop.found_existing) { @@ -6139,6 +6078,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt .runtime_loop = parent_block.runtime_loop, .runtime_index = parent_block.runtime_index, .error_return_trace_index = parent_block.error_return_trace_index, + .src_base_inst = parent_block.src_base_inst, }; defer child_block.instructions.deinit(gpa); @@ -6333,14 +6273,13 @@ fn resolveAnalyzedBlock( const type_src = src; // TODO: better source location if (try sema.typeRequiresComptime(resolved_ty)) { const msg = msg: { - const msg = try sema.errMsg(child_block, type_src, "value with comptime-only type '{}' depends on runtime control flow", .{resolved_ty.fmt(mod)}); + const msg = try sema.errMsg(type_src, "value with comptime-only type '{}' depends on runtime control flow", .{resolved_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?; - try mod.errNoteNonLazy(runtime_src, msg, "runtime control flow here", .{}); + try sema.errNote(runtime_src, msg, "runtime control flow here", .{}); - const child_src_decl = mod.declPtr(child_block.src_decl); - try sema.explainWhyTypeIsComptime(msg, child_src_decl.toSrcLoc(type_src, mod), resolved_ty); + try sema.explainWhyTypeIsComptime(msg, type_src, resolved_ty); break :msg msg; }; @@ -6433,8 +6372,8 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const options_src = block.builtinCallArgSrc(inst_data.src_node, 1); const decl_name = try mod.intern_pool.getOrPutString( mod.gpa, sema.code.nullTerminatedString(extra.decl_name), @@ -6448,13 +6387,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void break :index_blk maybe_index orelse return sema.failWithBadMemberAccess(block, container_ty, operand_src, decl_name); } else try sema.lookupIdentifier(block, operand_src, decl_name); - const options = sema.resolveExportOptions(block, .unneeded, extra.options) catch |err| switch (err) { - error.NeededSourceLocation => { - _ = try sema.resolveExportOptions(block, options_src, extra.options); - unreachable; - }, - else => |e| return e, - }; + const options = try sema.resolveExportOptions(block, options_src, extra.options); { try sema.ensureDeclAnalyzed(decl_index); const exported_decl = mod.declPtr(decl_index); @@ -6473,8 +6406,8 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.ExportValue, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const options_src = block.builtinCallArgSrc(inst_data.src_node, 1); const operand = try sema.resolveInstConst(block, operand_src, extra.operand, .{ .needed_comptime_reason = "export target must be comptime-known", }); @@ -6490,7 +6423,6 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError .opts = options, .src = src, .owner_decl = sema.owner_decl_index, - .src_decl = block.src_decl, .exported = .{ .value = operand.toIntern() }, .status = .in_progress, }); @@ -6515,11 +6447,10 @@ pub fn analyzeExport( if (!try sema.validateExternType(export_ty, .other)) { const msg = msg: { - const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{export_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "unable to export type '{}'", .{export_ty.fmt(mod)}); errdefer msg.destroy(gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), export_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); try sema.addDeclaredHereNote(msg, export_ty); break :msg msg; @@ -6538,7 +6469,6 @@ pub fn analyzeExport( .opts = options, .src = src, .owner_decl = sema.owner_decl_index, - .src_decl = block.src_decl, .exported = .{ .decl_index = exported_decl_index }, .status = .in_progress, }); @@ -6578,8 +6508,8 @@ fn addExport(mod: *Module, export_init: Module.Export) error{OutOfMemory}!void { fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { const mod = sema.mod; const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const src = LazySrcLoc.nodeOffset(extra.node); + const operand_src = block.builtinCallArgSrc(extra.node, 0); + const src = block.nodeOffset(extra.node); const alignment = try sema.resolveAlign(block, operand_src, extra.operand); if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) { return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ @@ -6598,9 +6528,9 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst if (sema.prev_stack_alignment_src) |prev_src| { const msg = msg: { - const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{}); + const msg = try sema.errMsg(src, "multiple @setAlignStack in the same function body", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, prev_src, msg, "other instance here", .{}); + try sema.errNote(prev_src, msg, "other instance here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -6621,7 +6551,7 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) const mod = sema.mod; const ip = &mod.intern_pool; const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const operand_src = block.builtinCallArgSrc(extra.node, 0); const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, .{ .needed_comptime_reason = "operand to @setCold must be comptime-known", }); @@ -6631,7 +6561,7 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const src = block.builtinCallArgSrc(extra.node, 0); block.float_mode = try sema.resolveBuiltinEnum(block, src, extra.operand, "FloatMode", .{ .needed_comptime_reason = "operand to @setFloatMode must be comptime-known", }); @@ -6639,7 +6569,7 @@ fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); block.want_safety = try sema.resolveConstBool(block, operand_src, inst_data.operand, .{ .needed_comptime_reason = "operand to @setRuntimeSafety must be comptime-known", }); @@ -6649,7 +6579,7 @@ fn zirFence(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) Co if (block.is_comptime) return; const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const order_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const order_src = block.builtinCallArgSrc(extra.node, 0); const order = try sema.resolveAtomicOrder(block, order_src, extra.operand, .{ .needed_comptime_reason = "atomic order of @fence must be comptime-known", }); @@ -6679,7 +6609,7 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError if (label.zir_block == zir_block) { const br_ref = try start_block.addBr(label.merges.block_inst, operand); const src_loc = if (extra.operand_src_node != Zir.Inst.Break.no_src_node) - LazySrcLoc.nodeOffset(extra.operand_src_node) + start_block.nodeOffset(extra.operand_src_node) else null; try label.merges.src_locs.append(sema.gpa, src_loc); @@ -6906,12 +6836,14 @@ fn lookupInNamespace( }, else => { const msg = msg: { - const msg = try sema.errMsg(block, src, "ambiguous reference", .{}); + const msg = try sema.errMsg(src, "ambiguous reference", .{}); errdefer msg.destroy(gpa); for (candidates.items) |candidate_index| { const candidate = mod.declPtr(candidate_index); - const src_loc = candidate.srcLoc(mod); - try mod.errNoteNonLazy(src_loc, msg, "declared here", .{}); + try sema.errNote(.{ + .base_node_inst = candidate.zir_decl_index.unwrap().?, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }, msg, "declared here", .{}); } break :msg msg; }; @@ -6953,16 +6885,16 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref if (!block.ownerModule().error_tracing) return .none; const stack_trace_ty = sema.getBuiltinType("StackTrace") catch |err| switch (err) { - error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, + error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, else => |e| return e, }; sema.resolveTypeFields(stack_trace_ty) catch |err| switch (err) { - error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, + error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, else => |e| return e, }; const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls); - const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, .unneeded) catch |err| switch (err) { - error.AnalysisFail, error.NeededSourceLocation => @panic("std.builtin.StackTrace is corrupt"), + const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) { + error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"), error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, error.OutOfMemory => |e| return e, }; @@ -7070,7 +7002,7 @@ fn zirCall( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; + const callee_src = block.src(.{ .node_offset_call_func = inst_data.src_node }); const call_src = block.nodeOffset(inst_data.src_node); const ExtraType = switch (kind) { .direct => Zir.Inst.Call, @@ -7092,7 +7024,7 @@ fn zirCall( sema.code.nullTerminatedString(extra.data.field_name_start), .no_embedded_nulls, ); - const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; + const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src); }, }; @@ -7202,11 +7134,11 @@ fn checkCallArgumentCount( opt_child.childType(mod).zigTypeTag(mod) == .Fn)) { const msg = msg: { - const msg = try sema.errMsg(block, func_src, "cannot call optional type '{}'", .{ + const msg = try sema.errMsg(func_src, "cannot call optional type '{}'", .{ callee_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, func_src, msg, "consider using '.?', 'orelse' or 'if'", .{}); + try sema.errNote(func_src, msg, "consider using '.?', 'orelse' or 'if'", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -7232,7 +7164,6 @@ fn checkCallArgumentCount( const variadic_str = if (func_ty_info.is_var_args) "at least " else ""; const msg = msg: { const msg = try sema.errMsg( - block, func_src, "{s}expected {s}{d} argument(s), found {d}", .{ @@ -7244,7 +7175,12 @@ fn checkCallArgumentCount( ); errdefer msg.destroy(sema.gpa); - if (maybe_decl) |fn_decl| try mod.errNoteNonLazy(fn_decl.srcLoc(mod), msg, "function declared here", .{}); + if (maybe_decl) |fn_decl| { + try sema.errNote(.{ + .base_node_inst = fn_decl.zir_decl_index.unwrap().?, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }, msg, "function declared here", .{}); + } break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -7352,18 +7288,16 @@ const CallArgsInfo = union(enum) { fn argSrc(cai: CallArgsInfo, block: *Block, arg_index: usize) LazySrcLoc { return switch (cai) { .resolved => |resolved| resolved.src, - .call_builtin => |call_builtin| .{ .call_arg = .{ - .decl = block.src_decl, + .call_builtin => |call_builtin| block.src(.{ .call_arg = .{ .call_node_offset = call_builtin.call_node_offset, .arg_index = @intCast(arg_index), - } }, + } }), .zir_call => |zir_call| if (arg_index == 0 and zir_call.bound_arg != .none) { return zir_call.bound_arg_src; - } else .{ .call_arg = .{ - .decl = block.src_decl, + } else block.src(.{ .call_arg = .{ .call_node_offset = zir_call.call_node_offset, .arg_index = @intCast(arg_index - @intFromBool(zir_call.bound_arg != .none)), - } }, + } }), }; } @@ -7475,7 +7409,6 @@ const InlineCallSema = struct { other_error_return_trace_index_on_fn_entry: Air.Inst.Ref, other_generic_owner: InternPool.Index, other_generic_call_src: LazySrcLoc, - other_generic_call_decl: InternPool.OptionalDeclIndex, /// Sema should currently be set up for the caller (i.e. unchanged yet). This init will not /// change that. The other parameters contain data for the callee Sema. The other modified @@ -7497,8 +7430,7 @@ const InlineCallSema = struct { .other_inst_map = .{}, .other_error_return_trace_index_on_fn_entry = callee_error_return_trace_index_on_fn_entry, .other_generic_owner = .none, - .other_generic_call_src = .unneeded, - .other_generic_call_decl = .none, + .other_generic_call_src = LazySrcLoc.unneeded, }; } @@ -7545,7 +7477,6 @@ const InlineCallSema = struct { std.mem.swap(InstMap, &ics.sema.inst_map, &ics.other_inst_map); std.mem.swap(InternPool.Index, &ics.sema.generic_owner, &ics.other_generic_owner); std.mem.swap(LazySrcLoc, &ics.sema.generic_call_src, &ics.other_generic_call_src); - std.mem.swap(InternPool.OptionalDeclIndex, &ics.sema.generic_call_decl, &ics.other_generic_call_decl); std.mem.swap(Air.Inst.Ref, &ics.sema.error_return_trace_index_on_fn_entry, &ics.other_error_return_trace_index_on_fn_entry); // zig fmt: on } @@ -7577,14 +7508,16 @@ fn analyzeCall( const maybe_decl = try sema.funcDeclSrc(func); const msg = msg: { const msg = try sema.errMsg( - block, func_src, "unable to call function with naked calling convention", .{}, ); errdefer msg.destroy(sema.gpa); - if (maybe_decl) |fn_decl| try mod.errNoteNonLazy(fn_decl.srcLoc(mod), msg, "function declared here", .{}); + if (maybe_decl) |fn_decl| try sema.errNote(.{ + .base_node_inst = fn_decl.zir_decl_index.unwrap().?, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }, msg, "function declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -7623,7 +7556,6 @@ fn analyzeCall( is_inline_call = ct; if (ct) { comptime_reason = &.{ .comptime_ret_ty = .{ - .block = block, .func = func, .func_src = func_src, .return_ty = Type.fromInterned(func_ty_info.return_type), @@ -7637,12 +7569,12 @@ fn analyzeCall( if (sema.func_is_naked and !is_inline_call and !is_comptime_call) { const msg = msg: { - const msg = try sema.errMsg(block, call_src, "runtime {s} not allowed in naked function", .{@tagName(operation)}); + const msg = try sema.errMsg(call_src, "runtime {s} not allowed in naked function", .{@tagName(operation)}); errdefer msg.destroy(sema.gpa); switch (operation) { .call, .@"@call", .@"@panic", .@"error return" => {}, - .@"safety check" => try sema.errNote(block, call_src, msg, "use @setRuntimeSafety to disable runtime safety", .{}), + .@"safety check" => try sema.errNote(call_src, msg, "use @setRuntimeSafety to disable runtime safety", .{}), } break :msg msg; }; @@ -7669,7 +7601,6 @@ fn analyzeCall( is_inline_call = true; is_comptime_call = true; comptime_reason = &.{ .comptime_ret_ty = .{ - .block = block, .func = func, .func_src = func_src, .return_ty = Type.fromInterned(func_ty_info.return_type), @@ -7776,6 +7707,7 @@ fn analyzeCall( .runtime_cond = block.runtime_cond, .runtime_loop = block.runtime_loop, .runtime_index = block.runtime_index, + .src_base_inst = fn_owner_decl.zir_decl_index.unwrap().?, }; const merges = &child_block.inlining.?.merges; @@ -7849,7 +7781,7 @@ fn analyzeCall( var block_it = block; while (block_it.inlining) |parent_inlining| { if (!parent_inlining.has_comptime_args and parent_inlining.func == module_fn_index) { - const err_msg = try sema.errMsg(block, call_src, "inline call is recursive", .{}); + const err_msg = try sema.errMsg(call_src, "inline call is recursive", .{}); return sema.failWithOwnedErrorMsg(null, err_msg); } block_it = parent_inlining.call_block; @@ -7864,7 +7796,7 @@ fn analyzeCall( try sema.resolveInlineBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst.resolve(ip)) else try sema.resolveInst(fn_info.ret_ty_ref); - const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; + const ret_ty_src: LazySrcLoc = .{ .base_node_inst = module_fn.zir_body_inst, .offset = .{ .node_offset_fn_type_ret_ty = 0 } }; sema.fn_ret_ty = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); if (module_fn.analysis(ip).inferred_error_set) { // Create a fresh inferred error set type for inline/comptime calls. @@ -7935,7 +7867,7 @@ fn analyzeCall( }; if (is_comptime_call) { - const result_val = try sema.resolveConstValue(block, .unneeded, result, undefined); + const result_val = try sema.resolveConstValue(block, LazySrcLoc.unneeded, result, undefined); const result_interned = result_val.toIntern(); // Transform ad-hoc inferred error set types into concrete error sets. @@ -8276,7 +8208,6 @@ fn instantiateGenericCall( .comptime_args = comptime_args, .generic_owner = generic_owner, .generic_call_src = call_src, - .generic_call_decl = block.src_decl.toOptional(), .branch_quota = sema.branch_quota, .branch_count = sema.branch_count, .comptime_err_ret_trace = sema.comptime_err_ret_trace, @@ -8291,6 +8222,7 @@ fn instantiateGenericCall( .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = fn_owner_decl.zir_decl_index.unwrap().?, }; defer child_block.instructions.deinit(gpa); @@ -8321,18 +8253,15 @@ fn instantiateGenericCall( const prev_no_partial_func_ty = child_sema.no_partial_func_ty; const prev_generic_owner = child_sema.generic_owner; const prev_generic_call_src = child_sema.generic_call_src; - const prev_generic_call_decl = child_sema.generic_call_decl; child_block.params = .{}; child_sema.no_partial_func_ty = true; child_sema.generic_owner = .none; - child_sema.generic_call_src = .unneeded; - child_sema.generic_call_decl = .none; + child_sema.generic_call_src = LazySrcLoc.unneeded; defer { child_block.params = prev_params; child_sema.no_partial_func_ty = prev_no_partial_func_ty; child_sema.generic_owner = prev_generic_owner; child_sema.generic_call_src = prev_generic_call_src; - child_sema.generic_call_decl = prev_generic_call_decl; } const param_ty_inst = try child_sema.resolveInlineBody(&child_block, param_ty_body, param_inst); @@ -8372,14 +8301,14 @@ fn instantiateGenericCall( .param_anytype_comptime, => return sema.failWithOwnedErrorMsg(block, msg: { const arg_src = args_info.argSrc(block, arg_index); - const msg = try sema.errMsg(block, arg_src, "runtime-known argument passed to comptime parameter", .{}); + const msg = try sema.errMsg(arg_src, "runtime-known argument passed to comptime parameter", .{}); errdefer msg.destroy(sema.gpa); const param_src = child_block.tokenOffset(switch (param_tag) { .param_comptime => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].pl_tok.src_tok, .param_anytype_comptime => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].str_tok.src_tok, else => unreachable, }); - try child_sema.errNote(&child_block, param_src, msg, "declared comptime here", .{}); + try child_sema.errNote(param_src, msg, "declared comptime here", .{}); break :msg msg; }), @@ -8387,16 +8316,15 @@ fn instantiateGenericCall( .param_anytype, => return sema.failWithOwnedErrorMsg(block, msg: { const arg_src = args_info.argSrc(block, arg_index); - const msg = try sema.errMsg(block, arg_src, "runtime-known argument passed to parameter of comptime-only type", .{}); + const msg = try sema.errMsg(arg_src, "runtime-known argument passed to parameter of comptime-only type", .{}); errdefer msg.destroy(sema.gpa); const param_src = child_block.tokenOffset(switch (param_tag) { .param => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].pl_tok.src_tok, .param_anytype => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].str_tok.src_tok, else => unreachable, }); - try child_sema.errNote(&child_block, param_src, msg, "declared here", .{}); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(arg_src, mod), arg_ty); + try child_sema.errNote(param_src, msg, "declared here", .{}); + try sema.explainWhyTypeIsComptime(msg, arg_src, arg_ty); break :msg msg; }), @@ -8433,7 +8361,7 @@ fn instantiateGenericCall( // We've already handled parameters, so don't resolve the whole body. Instead, just // do the instructions after the params (i.e. the func itself). const new_func_inst = try child_sema.resolveInlineBody(&child_block, fn_info.param_body[args_info.count()..], fn_info.param_body_inst); - const callee_index = (child_sema.resolveConstDefinedValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern(); + const callee_index = (child_sema.resolveConstDefinedValue(&child_block, LazySrcLoc.unneeded, new_func_inst, undefined) catch unreachable).toIntern(); const callee = mod.funcInfo(callee_index); callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota); @@ -8520,7 +8448,7 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; + const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); const child_type = try sema.resolveType(block, operand_src, inst_data.operand); if (child_type.zigTypeTag(mod) == .Opaque) { return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(mod)}); @@ -8535,7 +8463,7 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin; - const maybe_wrapped_indexable_ty = sema.resolveType(block, .unneeded, bin.lhs) catch |err| switch (err) { + const maybe_wrapped_indexable_ty = sema.resolveType(block, LazySrcLoc.unneeded, bin.lhs) catch |err| switch (err) { // Since this is a ZIR instruction that returns a type, encountering // generic poison should not result in a failed compilation, but the // generic poison type. This prevents unnecessary failures when @@ -8558,7 +8486,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const maybe_wrapped_ptr_ty = sema.resolveType(block, .unneeded, un_node.operand) catch |err| switch (err) { + const maybe_wrapped_ptr_ty = sema.resolveType(block, LazySrcLoc.unneeded, un_node.operand) catch |err| switch (err) { error.GenericPoison => return .generic_poison_type, else => |e| return e, }; @@ -8592,7 +8520,7 @@ fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const vec_ty = sema.resolveType(block, .unneeded, un_node.operand) catch |err| switch (err) { + const vec_ty = sema.resolveType(block, LazySrcLoc.unneeded, un_node.operand) catch |err| switch (err) { // Since this is a ZIR instruction that returns a type, encountering // generic poison should not result in a failed compilation, but the // generic poison type. This prevents unnecessary failures when @@ -8609,8 +8537,8 @@ fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const len_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const elem_type_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const len: u32 = @intCast(try sema.resolveInt(block, len_src, extra.lhs, Type.u32, .{ .needed_comptime_reason = "vector length must be comptime-known", @@ -8630,8 +8558,8 @@ fn zirArrayType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const len_src: LazySrcLoc = .{ .node_offset_array_type_len = inst_data.src_node }; - const elem_src: LazySrcLoc = .{ .node_offset_array_type_elem = inst_data.src_node }; + const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node }); + const elem_src = block.src(.{ .node_offset_array_type_elem = inst_data.src_node }); const len = try sema.resolveInt(block, len_src, extra.lhs, Type.usize, .{ .needed_comptime_reason = "array length must be comptime-known", }); @@ -8651,9 +8579,9 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data; - const len_src: LazySrcLoc = .{ .node_offset_array_type_len = inst_data.src_node }; - const sentinel_src: LazySrcLoc = .{ .node_offset_array_type_sentinel = inst_data.src_node }; - const elem_src: LazySrcLoc = .{ .node_offset_array_type_elem = inst_data.src_node }; + const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node }); + const sentinel_src = block.src(.{ .node_offset_array_type_sentinel = inst_data.src_node }); + const elem_src = block.src(.{ .node_offset_array_type_elem = inst_data.src_node }); const len = try sema.resolveInt(block, len_src, extra.len, Type.usize, .{ .needed_comptime_reason = "array length must be comptime-known", }); @@ -8691,7 +8619,7 @@ fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro return sema.failWithUseOfAsync(block, block.nodeOffset(inst_data.src_node)); } const mod = sema.mod; - const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node }; + const operand_src = block.src(.{ .node_offset_anyframe_type = inst_data.src_node }); const return_type = try sema.resolveType(block, operand_src, inst_data.operand); const anyframe_type = try mod.anyframeType(return_type); @@ -8705,8 +8633,8 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const error_set = try sema.resolveType(block, lhs_src, extra.lhs); const payload = try sema.resolveType(block, rhs_src, extra.rhs); @@ -8758,8 +8686,8 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD const mod = sema.mod; const ip = &mod.intern_pool; const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const src = block.nodeOffset(extra.node); + const operand_src = block.builtinCallArgSrc(extra.node, 0); const uncasted_operand = try sema.resolveInst(extra.operand); const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src); const err_int_ty = try mod.errorIntType(); @@ -8801,8 +8729,8 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD const mod = sema.mod; const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const src = block.nodeOffset(extra.node); + const operand_src = block.builtinCallArgSrc(extra.node, 0); const uncasted_operand = try sema.resolveInst(extra.operand); const err_int_ty = try mod.errorIntType(); const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src); @@ -8841,16 +8769,16 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr const ip = &mod.intern_pool; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); if (sema.typeOf(lhs).zigTypeTag(mod) == .Bool and sema.typeOf(rhs).zigTypeTag(mod) == .Bool) { const msg = msg: { - const msg = try sema.errMsg(block, lhs_src, "expected error set type, found 'bool'", .{}); + const msg = try sema.errMsg(lhs_src, "expected error set type, found 'bool'", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "'||' merges error sets; 'or' performs boolean OR", .{}); + try sema.errNote(src, msg, "'||' merges error sets; 'or' performs boolean OR", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -8905,7 +8833,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); @@ -8963,7 +8891,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt"); const operand = try sema.resolveInst(extra.rhs); @@ -9379,7 +9307,7 @@ fn zirFunc( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); const target = sema.mod.getTarget(); - const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = inst_data.src_node }; + const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = inst_data.src_node }); var extra_index = extra.end; @@ -9460,18 +9388,15 @@ fn resolveGenericBody( const prev_no_partial_func_type = sema.no_partial_func_ty; const prev_generic_owner = sema.generic_owner; const prev_generic_call_src = sema.generic_call_src; - const prev_generic_call_decl = sema.generic_call_decl; block.params = .{}; sema.no_partial_func_ty = true; sema.generic_owner = .none; - sema.generic_call_src = .unneeded; - sema.generic_call_decl = .none; + sema.generic_call_src = LazySrcLoc.unneeded; defer { block.params = prev_params; sema.no_partial_func_ty = prev_no_partial_func_type; sema.generic_owner = prev_generic_owner; sema.generic_call_src = prev_generic_call_src; - sema.generic_call_decl = prev_generic_call_decl; } const uncasted = sema.resolveInlineBody(block, body, func_inst) catch |err| break :err err; @@ -9581,9 +9506,9 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: if (!callConvSupportsVarArgs(cc)) { const msg = msg: { - const msg = try sema.errMsg(block, src, "variadic function does not support '.{s}' calling convention", .{@tagName(cc)}); + const msg = try sema.errMsg(src, "variadic function does not support '.{s}' calling convention", .{@tagName(cc)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "supported calling conventions: {}", .{CallingConventionsSupportingVarArgsList{}}); + try sema.errNote(src, msg, "supported calling conventions: {}", .{CallingConventionsSupportingVarArgsList{}}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -9623,9 +9548,9 @@ fn funcCommon( const gpa = sema.gpa; const target = mod.getTarget(); const ip = &mod.intern_pool; - const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; - const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset }; - const func_src = LazySrcLoc.nodeOffset(src_node_offset); + const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); + const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); + const func_src = block.nodeOffset(src_node_offset); var is_generic = bare_return_type.isGenericPoison() or alignment == null or @@ -9654,11 +9579,10 @@ fn funcCommon( const index = std.math.cast(u5, i) orelse break :blk false; break :blk @as(u1, @truncate(noalias_bits >> index)) != 0; }; - const param_src: LazySrcLoc = .{ .fn_proto_param = .{ - .decl = block.src_decl, + const param_src = block.src(.{ .fn_proto_param = .{ .fn_proto_node_offset = src_node_offset, .param_index = @intCast(i), - } }; + } }); const requires_comptime = try sema.typeRequiresComptime(param_ty); if (param_is_comptime or requires_comptime) { comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error @@ -9679,13 +9603,12 @@ fn funcCommon( } if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) { const msg = msg: { - const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ + const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ param_ty.fmt(mod), @tagName(cc_resolved), }); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(param_src, mod), param_ty, .param_ty); + try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty); try sema.addDeclaredHereNote(msg, param_ty); break :msg msg; @@ -9694,13 +9617,12 @@ fn funcCommon( } if (is_source_decl and requires_comptime and !param_is_comptime and has_body and !block.is_comptime) { const msg = msg: { - const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{ + const msg = try sema.errMsg(param_src, "parameter of type '{}' must be declared comptime", .{ param_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(param_src, mod), param_ty); + try sema.explainWhyTypeIsComptime(msg, param_src, param_ty); try sema.addDeclaredHereNote(msg, param_ty); break :msg msg; @@ -9861,9 +9783,9 @@ fn funcCommon( assert(section != .generic); assert(address_space != null); assert(!is_generic); - if (opt_lib_name) |lib_name| try sema.handleExternLibName(block, .{ + if (opt_lib_name) |lib_name| try sema.handleExternLibName(block, block.src(.{ .node_offset_lib_name = src_node_offset, - }, lib_name); + }), lib_name); const func_index = try ip.getExternFunc(gpa, .{ .ty = func_ty, .decl = sema.owner_decl_index, @@ -9975,13 +9897,12 @@ fn finishFunc( !try sema.validateExternType(return_type, .ret_ty)) { const msg = msg: { - const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ + const msg = try sema.errMsg(ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ return_type.fmt(mod), @tagName(cc_resolved), }); errdefer msg.destroy(gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(ret_ty_src, mod), return_type, .ret_ty); + try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, return_type, .ret_ty); try sema.addDeclaredHereNote(msg, return_type); break :msg msg; @@ -9997,12 +9918,11 @@ fn finishFunc( } else break :comptime_check; const msg = try sema.errMsg( - block, ret_ty_src, "function with comptime-only return type '{}' requires all parameters to be comptime", .{return_type.fmt(mod)}, ); - try sema.explainWhyTypeIsComptime(msg, sema.owner_decl.toSrcLoc(ret_ty_src, mod), return_type); + try sema.explainWhyTypeIsComptime(msg, ret_ty_src, return_type); const tags = sema.code.instructions.items(.tag); const data = sema.code.instructions.items(.data); @@ -10020,9 +9940,9 @@ fn finishFunc( }); const name = sema.code.nullTerminatedString(name_nts); if (name.len != 0) { - try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{name}); + try sema.errNote(param_src, msg, "param '{s}' is required to be comptime", .{name}); } else { - try sema.errNote(block, param_src, msg, "param is required to be comptime", .{}); + try sema.errNote(param_src, msg, "param is required to be comptime", .{}); } } } @@ -10112,18 +10032,15 @@ fn zirParam( const prev_no_partial_func_type = sema.no_partial_func_ty; const prev_generic_owner = sema.generic_owner; const prev_generic_call_src = sema.generic_call_src; - const prev_generic_call_decl = sema.generic_call_decl; block.params = .{}; sema.no_partial_func_ty = true; sema.generic_owner = .none; - sema.generic_call_src = .unneeded; - sema.generic_call_decl = .none; + sema.generic_call_src = LazySrcLoc.unneeded; defer { block.params = prev_params; sema.no_partial_func_ty = prev_no_partial_func_type; sema.generic_owner = prev_generic_owner; sema.generic_call_src = prev_generic_call_src; - sema.generic_call_decl = prev_generic_call_decl; } if (sema.resolveInlineBody(block, body, inst)) |param_ty_inst| { @@ -10265,7 +10182,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const zcu = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const ptr_ty = operand_ty.scalarType(zcu); @@ -10276,10 +10193,9 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const pointee_ty = ptr_ty.childType(zcu); if (try sema.typeRequiresComptime(ptr_ty)) { const msg = msg: { - const msg = try sema.errMsg(block, ptr_src, "comptime-only type '{}' has no pointer address", .{pointee_ty.fmt(zcu)}); + const msg = try sema.errMsg(ptr_src, "comptime-only type '{}' has no pointer address", .{pointee_ty.fmt(zcu)}); errdefer msg.destroy(sema.gpa); - const src_decl = zcu.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(ptr_src, zcu), pointee_ty); + try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -10340,7 +10256,7 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; + const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; const field_name = try mod.intern_pool.getOrPutString( sema.gpa, @@ -10358,7 +10274,7 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; + const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; const field_name = try mod.intern_pool.getOrPutString( sema.gpa, @@ -10376,7 +10292,7 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const field_name_src: LazySrcLoc = .{ .node_offset_field_name_init = inst_data.src_node }; + const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; const field_name = try mod.intern_pool.getOrPutString( sema.gpa, @@ -10401,7 +10317,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; const object = try sema.resolveInst(extra.lhs); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ @@ -10416,7 +10332,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; const object_ptr = try sema.resolveInst(extra.lhs); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ @@ -10431,7 +10347,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast"); @@ -10601,7 +10517,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast"); @@ -10627,10 +10543,10 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .Enum => { const msg = msg: { - const msg = try sema.errMsg(block, src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); switch (operand_ty.zigTypeTag(mod)) { - .Int, .ComptimeInt => try sema.errNote(block, src, msg, "use @enumFromInt to cast from '{}'", .{operand_ty.fmt(mod)}), + .Int, .ComptimeInt => try sema.errNote(src, msg, "use @enumFromInt to cast from '{}'", .{operand_ty.fmt(mod)}), else => {}, } @@ -10641,11 +10557,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .Pointer => { const msg = msg: { - const msg = try sema.errMsg(block, src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); switch (operand_ty.zigTypeTag(mod)) { - .Int, .ComptimeInt => try sema.errNote(block, src, msg, "use @ptrFromInt to cast from '{}'", .{operand_ty.fmt(mod)}), - .Pointer => try sema.errNote(block, src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(mod)}), + .Int, .ComptimeInt => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{}'", .{operand_ty.fmt(mod)}), + .Pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(mod)}), else => {}, } @@ -10691,10 +10607,10 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .Enum => { const msg = msg: { - const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(mod)}); + const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); switch (dest_ty.zigTypeTag(mod)) { - .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @intFromEnum to cast to '{}'", .{dest_ty.fmt(mod)}), + .Int, .ComptimeInt => try sema.errNote(operand_src, msg, "use @intFromEnum to cast to '{}'", .{dest_ty.fmt(mod)}), else => {}, } @@ -10704,11 +10620,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air }, .Pointer => { const msg = msg: { - const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(mod)}); + const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); switch (dest_ty.zigTypeTag(mod)) { - .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @intFromPtr to cast to '{}'", .{dest_ty.fmt(mod)}), - .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(mod)}), + .Int, .ComptimeInt => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{}'", .{dest_ty.fmt(mod)}), + .Pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(mod)}), else => {}, } @@ -10744,7 +10660,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast"); @@ -10835,7 +10751,7 @@ fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node }; + const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const array = try sema.resolveInst(extra.lhs); const uncoerced_elem_index = try sema.resolveInst(extra.rhs); @@ -10851,7 +10767,7 @@ fn zirElemValImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm; const array = try sema.resolveInst(inst_data.operand); const elem_index = try mod.intRef(Type.usize, inst_data.idx); - return sema.elemVal(block, .unneeded, array, elem_index, .unneeded, false); + return sema.elemVal(block, LazySrcLoc.unneeded, array, elem_index, LazySrcLoc.unneeded, false); } fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -10866,14 +10782,14 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const elem_index = try sema.resolveInst(extra.rhs); const indexable_ty = sema.typeOf(array_ptr); if (indexable_ty.zigTypeTag(mod) != .Pointer) { - const capture_src: LazySrcLoc = .{ .for_capture_from_input = inst_data.src_node }; + const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node }); const msg = msg: { - const msg = try sema.errMsg(block, capture_src, "pointer capture of non pointer type '{}'", .{ + const msg = try sema.errMsg(capture_src, "pointer capture of non pointer type '{}'", .{ indexable_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); if (indexable_ty.isIndexable(mod)) { - try sema.errNote(block, src, msg, "consider using '&' here", .{}); + try sema.errNote(src, msg, "consider using '&' here", .{}); } break :msg msg; }; @@ -10888,7 +10804,7 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node }; + const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const array_ptr = try sema.resolveInst(extra.lhs); const uncoerced_elem_index = try sema.resolveInst(extra.rhs); @@ -10925,11 +10841,11 @@ fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const extra = sema.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data; const array_ptr = try sema.resolveInst(extra.lhs); const start = try sema.resolveInst(extra.start); - const ptr_src: LazySrcLoc = .{ .node_offset_slice_ptr = inst_data.src_node }; - const start_src: LazySrcLoc = .{ .node_offset_slice_start = inst_data.src_node }; - const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node }; + const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); + const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); + const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); - return sema.analyzeSlice(block, src, array_ptr, start, .none, .none, .unneeded, ptr_src, start_src, end_src, false); + return sema.analyzeSlice(block, src, array_ptr, start, .none, .none, LazySrcLoc.unneeded, ptr_src, start_src, end_src, false); } fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -10942,11 +10858,11 @@ fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const array_ptr = try sema.resolveInst(extra.lhs); const start = try sema.resolveInst(extra.start); const end = try sema.resolveInst(extra.end); - const ptr_src: LazySrcLoc = .{ .node_offset_slice_ptr = inst_data.src_node }; - const start_src: LazySrcLoc = .{ .node_offset_slice_start = inst_data.src_node }; - const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node }; + const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); + const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); + const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); - return sema.analyzeSlice(block, src, array_ptr, start, end, .none, .unneeded, ptr_src, start_src, end_src, false); + return sema.analyzeSlice(block, src, array_ptr, start, end, .none, LazySrcLoc.unneeded, ptr_src, start_src, end_src, false); } fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -10955,15 +10871,15 @@ fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const sentinel_src: LazySrcLoc = .{ .node_offset_slice_sentinel = inst_data.src_node }; + const sentinel_src = block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data; const array_ptr = try sema.resolveInst(extra.lhs); const start = try sema.resolveInst(extra.start); const end: Air.Inst.Ref = if (extra.end == .none) .none else try sema.resolveInst(extra.end); const sentinel = try sema.resolveInst(extra.sentinel); - const ptr_src: LazySrcLoc = .{ .node_offset_slice_ptr = inst_data.src_node }; - const start_src: LazySrcLoc = .{ .node_offset_slice_start = inst_data.src_node }; - const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node }; + const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); + const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); + const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); return sema.analyzeSlice(block, src, array_ptr, start, end, sentinel, sentinel_src, ptr_src, start_src, end_src, false); } @@ -10979,13 +10895,13 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const start = try sema.resolveInst(extra.start); const len = try sema.resolveInst(extra.len); const sentinel = if (extra.sentinel == .none) .none else try sema.resolveInst(extra.sentinel); - const ptr_src: LazySrcLoc = .{ .node_offset_slice_ptr = inst_data.src_node }; - const start_src: LazySrcLoc = .{ .node_offset_slice_start = extra.start_src_node_offset }; - const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node }; + const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); + const start_src = block.src(.{ .node_offset_slice_start = extra.start_src_node_offset }); + const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); const sentinel_src: LazySrcLoc = if (sentinel == .none) - .unneeded + LazySrcLoc.unneeded else - .{ .node_offset_slice_sentinel = inst_data.src_node }; + block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true); } @@ -11019,8 +10935,8 @@ const SwitchProngAnalysis = struct { prong_type: enum { normal, special }, prong_body: []const Zir.Inst.Index, capture: Zir.Inst.SwitchBlock.ProngInfo.Capture, - /// Must use the `scalar_capture`, `special_capture`, or `multi_capture` union field. - raw_capture_src: Module.SwitchProngSrc, + /// Must use the `switch_capture` field in `offset`. + capture_src: LazySrcLoc, /// The set of all values which can reach this prong. May be undefined /// if the prong is special or contains ranges. case_vals: []const Air.Inst.Ref, @@ -11038,7 +10954,7 @@ const SwitchProngAnalysis = struct { ); if (has_tag_capture) { - const tag_ref = try spa.analyzeTagCapture(child_block, raw_capture_src, inline_case_capture); + const tag_ref = try spa.analyzeTagCapture(child_block, capture_src, inline_case_capture); sema.inst_map.putAssumeCapacity(spa.tag_capture_inst, tag_ref); } defer if (has_tag_capture) assert(sema.inst_map.remove(spa.tag_capture_inst)); @@ -11053,7 +10969,7 @@ const SwitchProngAnalysis = struct { child_block, capture == .by_ref, prong_type == .special, - raw_capture_src, + capture_src, case_vals, inline_case_capture, ); @@ -11079,8 +10995,8 @@ const SwitchProngAnalysis = struct { prong_type: enum { normal, special }, prong_body: []const Zir.Inst.Index, capture: Zir.Inst.SwitchBlock.ProngInfo.Capture, - /// Must use the `scalar`, `special`, or `multi_capture` union field. - raw_capture_src: Module.SwitchProngSrc, + /// Must use the `switch_capture` field in `offset`. + capture_src: LazySrcLoc, /// The set of all values which can reach this prong. May be undefined /// if the prong is special or contains ranges. case_vals: []const Air.Inst.Ref, @@ -11094,7 +11010,7 @@ const SwitchProngAnalysis = struct { const sema = spa.sema; if (has_tag_capture) { - const tag_ref = try spa.analyzeTagCapture(case_block, raw_capture_src, inline_case_capture); + const tag_ref = try spa.analyzeTagCapture(case_block, capture_src, inline_case_capture); sema.inst_map.putAssumeCapacity(spa.tag_capture_inst, tag_ref); } defer if (has_tag_capture) assert(sema.inst_map.remove(spa.tag_capture_inst)); @@ -11109,7 +11025,7 @@ const SwitchProngAnalysis = struct { case_block, capture == .by_ref, prong_type == .special, - raw_capture_src, + capture_src, case_vals, inline_case_capture, ); @@ -11130,23 +11046,18 @@ const SwitchProngAnalysis = struct { fn analyzeTagCapture( spa: SwitchProngAnalysis, block: *Block, - raw_capture_src: Module.SwitchProngSrc, + capture_src: LazySrcLoc, inline_case_capture: Air.Inst.Ref, ) CompileError!Air.Inst.Ref { const sema = spa.sema; const mod = sema.mod; const operand_ty = sema.typeOf(spa.operand); if (operand_ty.zigTypeTag(mod) != .Union) { - const zir_datas = sema.code.instructions.items(.data); - const switch_node_offset = zir_datas[@intFromEnum(spa.switch_block_inst)].pl_node.src_node; - const raw_tag_capture_src: Module.SwitchProngSrc = switch (raw_capture_src) { - .scalar_capture => |i| .{ .scalar_tag_capture = i }, - .multi_capture => |i| .{ .multi_tag_capture = i }, - .special_capture => .special_tag_capture, - else => unreachable, + const tag_capture_src: LazySrcLoc = .{ + .base_node_inst = capture_src.base_node_inst, + .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture }, }; - const capture_src = raw_tag_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none); - return sema.fail(block, capture_src, "cannot capture tag of non-union type '{}'", .{ + return sema.fail(block, tag_capture_src, "cannot capture tag of non-union type '{}'", .{ operand_ty.fmt(mod), }); } @@ -11159,7 +11070,7 @@ const SwitchProngAnalysis = struct { block: *Block, capture_byref: bool, is_special_prong: bool, - raw_capture_src: Module.SwitchProngSrc, + capture_src: LazySrcLoc, case_vals: []const Air.Inst.Ref, inline_case_capture: Air.Inst.Ref, ) CompileError!Air.Inst.Ref { @@ -11172,10 +11083,10 @@ const SwitchProngAnalysis = struct { const operand_ty = sema.typeOf(spa.operand); const operand_ptr_ty = if (capture_byref) sema.typeOf(spa.operand_ptr) else undefined; - const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_node_offset }; + const operand_src = block.src(.{ .node_offset_switch_operand = switch_node_offset }); if (inline_case_capture != .none) { - const item_val = sema.resolveConstDefinedValue(block, .unneeded, inline_case_capture, undefined) catch unreachable; + const item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inline_case_capture, undefined) catch unreachable; if (operand_ty.zigTypeTag(zcu) == .Union) { const field_index: u32 = @intCast(operand_ty.unionTagFieldIndex(item_val, zcu).?); const union_obj = zcu.typeToUnion(operand_ty).?; @@ -11216,7 +11127,7 @@ const SwitchProngAnalysis = struct { .ErrorSet => if (spa.else_error_ty) |ty| { return sema.bitCast(block, ty, spa.operand, operand_src, null); } else { - try block.addUnreachable(operand_src, false); + try sema.analyzeUnreachable(block, operand_src, false); return .unreachable_value; }, else => return spa.operand, @@ -11226,14 +11137,14 @@ const SwitchProngAnalysis = struct { switch (operand_ty.zigTypeTag(zcu)) { .Union => { const union_obj = zcu.typeToUnion(operand_ty).?; - const first_item_val = sema.resolveConstDefinedValue(block, .unneeded, case_vals[0], undefined) catch unreachable; + const first_item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, case_vals[0], undefined) catch unreachable; const first_field_index: u32 = zcu.unionTagFieldIndex(union_obj, first_item_val).?; const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[first_field_index]); const field_indices = try sema.arena.alloc(u32, case_vals.len); for (case_vals, field_indices) |item, *field_idx| { - const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; + const item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item, undefined) catch unreachable; field_idx.* = zcu.unionTagFieldIndex(union_obj, item_val).?; } @@ -11253,27 +11164,22 @@ const SwitchProngAnalysis = struct { } const case_srcs = try sema.arena.alloc(?LazySrcLoc, case_vals.len); - @memset(case_srcs, .unneeded); + for (case_srcs, 0..) |*case_src, i| { + case_src.* = .{ + .base_node_inst = capture_src.base_node_inst, + .offset = .{ .switch_case_item = .{ + .switch_node_offset = switch_node_offset, + .case_idx = capture_src.offset.switch_capture.case_idx, + .item_idx = .{ .kind = .single, .index = @intCast(i) }, + } }, + }; + } - break :capture_ty sema.resolvePeerTypes(block, .unneeded, dummy_captures, .{ .override = case_srcs }) catch |err| switch (err) { - error.NeededSourceLocation => { - // This must be a multi-prong so this must be a `multi_capture` src - const multi_idx = raw_capture_src.multi_capture; - const src_decl_ptr = zcu.declPtr(block.src_decl); - for (case_srcs, 0..) |*case_src, i| { - const raw_case_src: Module.SwitchProngSrc = .{ .multi = .{ .prong = multi_idx, .item = @intCast(i) } }; - case_src.* = raw_case_src.resolve(zcu, src_decl_ptr, switch_node_offset, .none); - } - const capture_src = raw_capture_src.resolve(zcu, src_decl_ptr, switch_node_offset, .none); - _ = sema.resolvePeerTypes(block, capture_src, dummy_captures, .{ .override = case_srcs }) catch |err1| switch (err1) { - error.AnalysisFail => { - const msg = sema.err orelse return error.AnalysisFail; - try sema.reparentOwnedErrorMsg(block, capture_src, msg, "capture group with incompatible types", .{}); - return error.AnalysisFail; - }, - else => |e| return e, - }; - unreachable; + break :capture_ty sema.resolvePeerTypes(block, capture_src, dummy_captures, .{ .override = case_srcs }) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return error.AnalysisFail; + try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{}); + return error.AnalysisFail; }, else => |e| return e, }; @@ -11301,28 +11207,23 @@ const SwitchProngAnalysis = struct { dummy.* = try zcu.undefRef(field_ptr_ty); } const case_srcs = try sema.arena.alloc(?LazySrcLoc, case_vals.len); - @memset(case_srcs, .unneeded); + for (case_srcs, 0..) |*case_src, i| { + case_src.* = .{ + .base_node_inst = capture_src.base_node_inst, + .offset = .{ .switch_case_item = .{ + .switch_node_offset = switch_node_offset, + .case_idx = capture_src.offset.switch_capture.case_idx, + .item_idx = .{ .kind = .single, .index = @intCast(i) }, + } }, + }; + } - break :resolve sema.resolvePeerTypes(block, .unneeded, dummy_captures, .{ .override = case_srcs }) catch |err| switch (err) { - error.NeededSourceLocation => { - // This must be a multi-prong so this must be a `multi_capture` src - const multi_idx = raw_capture_src.multi_capture; - const src_decl_ptr = zcu.declPtr(block.src_decl); - for (case_srcs, 0..) |*case_src, i| { - const raw_case_src: Module.SwitchProngSrc = .{ .multi = .{ .prong = multi_idx, .item = @intCast(i) } }; - case_src.* = raw_case_src.resolve(zcu, src_decl_ptr, switch_node_offset, .none); - } - const capture_src = raw_capture_src.resolve(zcu, src_decl_ptr, switch_node_offset, .none); - _ = sema.resolvePeerTypes(block, capture_src, dummy_captures, .{ .override = case_srcs }) catch |err1| switch (err1) { - error.AnalysisFail => { - const msg = sema.err orelse return error.AnalysisFail; - try sema.errNote(block, capture_src, msg, "this coercion is only possible when capturing by value", .{}); - try sema.reparentOwnedErrorMsg(block, capture_src, msg, "capture group with incompatible types", .{}); - return error.AnalysisFail; - }, - else => |e| return e, - }; - unreachable; + break :resolve sema.resolvePeerTypes(block, capture_src, dummy_captures, .{ .override = case_srcs }) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return error.AnalysisFail; + try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{}); + try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{}); + return error.AnalysisFail; }, else => |e| return e, }; @@ -11357,7 +11258,7 @@ const SwitchProngAnalysis = struct { const first_non_imc = in_mem: { for (field_indices, 0..) |field_idx, i| { const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); - if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), .unneeded, .unneeded)) { + if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), LazySrcLoc.unneeded, LazySrcLoc.unneeded)) { break :in_mem i; } } @@ -11380,7 +11281,7 @@ const SwitchProngAnalysis = struct { const next = first_non_imc + 1; for (field_indices[next..], next..) |field_idx, i| { const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); - if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), .unneeded, .unneeded)) { + if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), LazySrcLoc.unneeded, LazySrcLoc.unneeded)) { in_mem_coercible.unset(i); } } @@ -11409,20 +11310,19 @@ const SwitchProngAnalysis = struct { var coerce_block = block.makeSubBlock(); defer coerce_block.instructions.deinit(sema.gpa); + const case_src: LazySrcLoc = .{ + .base_node_inst = capture_src.base_node_inst, + .offset = .{ .switch_case_item = .{ + .switch_node_offset = switch_node_offset, + .case_idx = capture_src.offset.switch_capture.case_idx, + .item_idx = .{ .kind = .single, .index = @intCast(idx) }, + } }, + }; + const field_idx = field_indices[idx]; const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); const uncoerced = try coerce_block.addStructFieldVal(spa.operand, field_idx, field_ty); - const coerced = sema.coerce(&coerce_block, capture_ty, uncoerced, .unneeded) catch |err| switch (err) { - error.NeededSourceLocation => { - const multi_idx = raw_capture_src.multi_capture; - const src_decl_ptr = zcu.declPtr(block.src_decl); - const raw_case_src: Module.SwitchProngSrc = .{ .multi = .{ .prong = multi_idx, .item = @intCast(idx) } }; - const case_src = raw_case_src.resolve(zcu, src_decl_ptr, switch_node_offset, .none); - _ = try sema.coerce(&coerce_block, capture_ty, uncoerced, case_src); - unreachable; - }, - else => |e| return e, - }; + const coerced = try sema.coerce(&coerce_block, capture_ty, uncoerced, case_src); _ = try coerce_block.addBr(capture_block_inst, coerced); try cases_extra.ensureUnusedCapacity(3 + coerce_block.instructions.items.len); @@ -11476,7 +11376,6 @@ const SwitchProngAnalysis = struct { }, .ErrorSet => { if (capture_byref) { - const capture_src = raw_capture_src.resolve(zcu, zcu.declPtr(block.src_decl), switch_node_offset, .none); return sema.fail( block, capture_src, @@ -11486,7 +11385,7 @@ const SwitchProngAnalysis = struct { } if (case_vals.len == 1) { - const item_val = sema.resolveConstDefinedValue(block, .unneeded, case_vals[0], undefined) catch unreachable; + const item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, case_vals[0], undefined) catch unreachable; const item_ty = try zcu.singleErrorSetType(item_val.getErrorName(zcu).unwrap().?); return sema.bitCast(block, item_ty, spa.operand, operand_src, null); } @@ -11494,7 +11393,7 @@ const SwitchProngAnalysis = struct { var names: InferredErrorSet.NameMap = .{}; try names.ensureUnusedCapacity(sema.arena, case_vals.len); for (case_vals) |err| { - const err_val = sema.resolveConstDefinedValue(block, .unneeded, err, undefined) catch unreachable; + const err_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, err, undefined) catch unreachable; names.putAssumeCapacityNoClobber(err_val.getErrorName(zcu).unwrap().?, {}); } const error_ty = try zcu.errorSetFromUnsortedNames(names.keys()); @@ -11548,10 +11447,10 @@ fn switchCond( try sema.resolveTypeFields(operand_ty); const enum_ty = operand_ty.unionTagType(mod) orelse { const msg = msg: { - const msg = try sema.errMsg(block, src, "switch on union with no attached enum", .{}); + const msg = try sema.errMsg(src, "switch on union with no attached enum", .{}); errdefer msg.destroy(sema.gpa); - if (operand_ty.declSrcLocOrNull(mod)) |union_src| { - try mod.errNoteNonLazy(union_src, msg, "consider 'union(enum)' here", .{}); + if (operand_ty.srcLocOrNull(mod)) |union_src| { + try sema.errNote(union_src, msg, "consider 'union(enum)' here", .{}); } break :msg msg; }; @@ -11575,7 +11474,7 @@ fn switchCond( } } -const SwitchErrorSet = std.AutoHashMap(InternPool.NullTerminatedString, Module.SwitchProngSrc); +const SwitchErrorSet = std.AutoHashMap(InternPool.NullTerminatedString, LazySrcLoc); fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -11586,11 +11485,11 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const switch_src = block.nodeOffset(inst_data.src_node); const switch_src_node_offset = inst_data.src_node; - const switch_operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_src_node_offset }; - const else_prong_src: LazySrcLoc = .{ .node_offset_switch_special_prong = switch_src_node_offset }; + const switch_operand_src = block.src(.{ .node_offset_switch_operand = switch_src_node_offset }); + const else_prong_src = block.src(.{ .node_offset_switch_special_prong = switch_src_node_offset }); const extra = sema.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index); - const main_operand_src: LazySrcLoc = .{ .node_offset_if_cond = extra.data.main_src_node_offset }; - const main_src: LazySrcLoc = .{ .node_offset_main_token = extra.data.main_src_node_offset }; + const main_operand_src = block.src(.{ .node_offset_if_cond = extra.data.main_src_node_offset }); + const main_src = block.src(.{ .node_offset_main_token = extra.data.main_src_node_offset }); const raw_operand_val = try sema.resolveInst(extra.data.operand); @@ -11710,6 +11609,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp .runtime_index = block.runtime_index, .error_return_trace_index = block.error_return_trace_index, .want_safety = block.want_safety, + .src_base_inst = block.src_base_inst, }; const merges = &child_block.label.?.merges; defer child_block.instructions.deinit(gpa); @@ -11776,6 +11676,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp try sema.switchCond(block, switch_operand_src, spa.operand), err_val, operand_err_set_ty, + switch_src_node_offset, .{ .body = else_case.body, .end = else_case.end, @@ -11817,7 +11718,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp var sub_block = child_block.makeSubBlock(); sub_block.runtime_loop = null; - sub_block.runtime_cond = mod.declPtr(child_block.src_decl).toSrcLoc(main_operand_src, mod); + sub_block.runtime_cond = main_operand_src; sub_block.runtime_index.increment(); sub_block.need_debug_scope = null; // this body is emitted regardless defer sub_block.instructions.deinit(gpa); @@ -11894,8 +11795,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const src_node_offset = inst_data.src_node; - const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = src_node_offset }; - const special_prong_src: LazySrcLoc = .{ .node_offset_switch_special_prong = src_node_offset }; + const operand_src = block.src(.{ .node_offset_switch_operand = src_node_offset }); + const special_prong_src = block.src(.{ .node_offset_switch_special_prong = src_node_offset }); const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); const raw_operand_val: Air.Inst.Ref, const raw_operand_ptr: Air.Inst.Ref = blk: { @@ -11962,7 +11863,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union; // Duplicate checking variables later also used for `inline else`. - var seen_enum_fields: []?Module.SwitchProngSrc = &.{}; + var seen_enum_fields: []?LazySrcLoc = &.{}; var seen_errors = SwitchErrorSet.init(gpa); var range_set = RangeSet.init(gpa, mod); var true_count: u8 = 0; @@ -11985,21 +11886,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r if (special_prong == .under and (!operand_ty.isNonexhaustiveEnum(mod) or union_originally)) { const msg = msg: { const msg = try sema.errMsg( - block, src, "'_' prong only allowed when switching on non-exhaustive enums", .{}, ); errdefer msg.destroy(gpa); try sema.errNote( - block, special_prong_src, msg, "'_' prong here", .{}, ); try sema.errNote( - block, src, msg, "consider using 'else'", @@ -12014,7 +11912,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r switch (operand_ty.zigTypeTag(mod)) { .Union => unreachable, // handled in `switchCond` .Enum => { - seen_enum_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount(mod)); + seen_enum_fields = try gpa.alloc(?LazySrcLoc, operand_ty.enumFieldCount(mod)); empty_enum = seen_enum_fields.len == 0 and !operand_ty.isNonexhaustiveEnum(mod); @memset(seen_enum_fields, null); // `range_set` is used for non-exhaustive enum values that do not correspond to any tags. @@ -12034,8 +11932,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r &range_set, item_ref, operand_ty, - src_node_offset, - .{ .scalar = scalar_i }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .scalar, .index = @intCast(scalar_i) }, + .item_idx = .{ .kind = .single, .index = 0 }, + } }), )); } } @@ -12059,8 +11960,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r &range_set, item_ref, operand_ty, - src_node_offset, - .{ .multi = .{ .prong = multi_i, .item = @intCast(item_i) } }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, + } }), )); } @@ -12081,7 +11985,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r } else if (!all_tags_handled) { const msg = msg: { const msg = try sema.errMsg( - block, src, "switch must handle all possibilities", .{}, @@ -12099,8 +12002,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r .{field_name.fmt(&mod.intern_pool)}, ); } - try mod.errNoteNonLazy( - operand_ty.declSrcLoc(mod), + try sema.errNote( + operand_ty.srcLoc(mod), msg, "enum '{}' declared here", .{operand_ty.fmt(mod)}, @@ -12144,8 +12047,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r &range_set, item_ref, operand_ty, - src_node_offset, - .{ .scalar = scalar_i }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .scalar, .index = @intCast(scalar_i) }, + .item_idx = .{ .kind = .single, .index = 0 }, + } }), )); } } @@ -12168,8 +12074,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r &range_set, item_ref, operand_ty, - src_node_offset, - .{ .multi = .{ .prong = multi_i, .item = @intCast(item_i) } }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, + } }), )); } @@ -12187,8 +12096,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r item_first, item_last, operand_ty, - src_node_offset, - .{ .range = .{ .prong = multi_i, .item = range_i } }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + .item_idx = .{ .kind = .range, .index = @intCast(range_i) }, + } }), ); case_vals.appendAssumeCapacity(vals[0]); case_vals.appendAssumeCapacity(vals[1]); @@ -12239,8 +12151,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r &true_count, &false_count, item_ref, - src_node_offset, - .{ .scalar = scalar_i }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .scalar, .index = @intCast(scalar_i) }, + .item_idx = .{ .kind = .single, .index = 0 }, + } }), )); } } @@ -12263,8 +12178,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r &true_count, &false_count, item_ref, - src_node_offset, - .{ .multi = .{ .prong = multi_i, .item = @intCast(item_i) } }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, + } }), )); } @@ -12322,8 +12240,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r &seen_values, item_ref, operand_ty, - src_node_offset, - .{ .scalar = scalar_i }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .scalar, .index = @intCast(scalar_i) }, + .item_idx = .{ .kind = .single, .index = 0 }, + } }), )); } } @@ -12346,8 +12267,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r &seen_values, item_ref, operand_ty, - src_node_offset, - .{ .multi = .{ .prong = multi_i, .item = @intCast(item_i) } }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, + } }), )); } @@ -12417,6 +12341,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r .runtime_index = block.runtime_index, .want_safety = block.want_safety, .error_return_trace_index = block.error_return_trace_index, + .src_base_inst = block.src_base_inst, }; const merges = &child_block.label.?.merges; defer child_block.instructions.deinit(gpa); @@ -12430,6 +12355,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r operand, operand_val, operand_ty, + src_node_offset, special, case_vals, scalar_cases_len, @@ -12462,7 +12388,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r .special, special.body, special.capture, - .special_capture, + block.src(.{ .switch_capture = .{ + .switch_node_offset = src_node_offset, + .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, + } }), undefined, // case_vals may be undefined for special prongs .none, false, @@ -12529,9 +12458,9 @@ fn analyzeSwitchRuntimeBlock( union_originally: bool, maybe_union_ty: Type, err_set: bool, - src_node_offset: i32, + switch_node_offset: i32, special_prong_src: LazySrcLoc, - seen_enum_fields: []?Module.SwitchProngSrc, + seen_enum_fields: []?LazySrcLoc, seen_errors: SwitchErrorSet, range_set: RangeSet, true_count: u8, @@ -12552,7 +12481,7 @@ fn analyzeSwitchRuntimeBlock( var case_block = child_block.makeSubBlock(); case_block.runtime_loop = null; - case_block.runtime_cond = mod.declPtr(child_block.src_decl).toSrcLoc(operand_src, mod); + case_block.runtime_cond = operand_src; case_block.runtime_index.increment(); case_block.need_debug_scope = null; // this body is emitted regardless defer case_block.instructions.deinit(gpa); @@ -12574,7 +12503,7 @@ fn analyzeSwitchRuntimeBlock( // `item` is already guaranteed to be constant known. const analyze_body = if (union_originally) blk: { - const unresolved_item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; + const unresolved_item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item, undefined) catch unreachable; const item_val = sema.resolveLazyValue(unresolved_item_val) catch unreachable; const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?; break :blk field_ty.zigTypeTag(mod) != .NoReturn; @@ -12588,7 +12517,10 @@ fn analyzeSwitchRuntimeBlock( .normal, body, info.capture, - .{ .scalar_capture = @intCast(scalar_i) }, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .scalar, .index = @intCast(scalar_i) }, + } }), &.{item}, if (info.is_inline) item else .none, info.has_tag_capture, @@ -12643,8 +12575,8 @@ fn analyzeSwitchRuntimeBlock( const item_first_ref = range_items[0]; const item_last_ref = range_items[1]; - var item = sema.resolveConstDefinedValue(block, .unneeded, item_first_ref, undefined) catch unreachable; - const item_last = sema.resolveConstDefinedValue(block, .unneeded, item_last_ref, undefined) catch unreachable; + var item = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item_first_ref, undefined) catch unreachable; + const item_last = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item_last_ref, undefined) catch unreachable; while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({ // Previous validation has resolved any possible lazy values. @@ -12660,17 +12592,11 @@ fn analyzeSwitchRuntimeBlock( case_block.instructions.shrinkRetainingCapacity(0); case_block.error_return_trace_index = child_block.error_return_trace_index; - if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { - error.NeededSourceLocation => { - const case_src = Module.SwitchProngSrc{ - .range = .{ .prong = multi_i, .item = range_i }, - }; - const decl = mod.declPtr(case_block.src_decl); - try sema.emitBackwardBranch(block, case_src.resolve(mod, decl, src_node_offset, .none)); - unreachable; - }, - else => return err, - }; + if (emit_bb) try sema.emitBackwardBranch(block, block.src(.{ .switch_case_item = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + .item_idx = .{ .kind = .range, .index = @intCast(range_i) }, + } })); emit_bb = true; try spa.analyzeProngRuntime( @@ -12678,7 +12604,10 @@ fn analyzeSwitchRuntimeBlock( .normal, body, info.capture, - .{ .multi_capture = multi_i }, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + } }), undefined, // case_vals may be undefined for ranges item_ref, info.has_tag_capture, @@ -12701,22 +12630,16 @@ fn analyzeSwitchRuntimeBlock( case_block.error_return_trace_index = child_block.error_return_trace_index; const analyze_body = if (union_originally) blk: { - const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; + const item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item, undefined) catch unreachable; const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?; break :blk field_ty.zigTypeTag(mod) != .NoReturn; } else true; - if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { - error.NeededSourceLocation => { - const case_src = Module.SwitchProngSrc{ - .multi = .{ .prong = multi_i, .item = @intCast(item_i) }, - }; - const decl = mod.declPtr(case_block.src_decl); - try sema.emitBackwardBranch(block, case_src.resolve(mod, decl, src_node_offset, .none)); - unreachable; - }, - else => return err, - }; + if (emit_bb) try sema.emitBackwardBranch(block, block.src(.{ .switch_case_item = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, + } })); emit_bb = true; if (analyze_body) { @@ -12725,7 +12648,10 @@ fn analyzeSwitchRuntimeBlock( .normal, body, info.capture, - .{ .multi_capture = multi_i }, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + } }), &.{item}, item, info.has_tag_capture, @@ -12755,7 +12681,7 @@ fn analyzeSwitchRuntimeBlock( const analyze_body = if (union_originally) for (items) |item| { - const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; + const item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item, undefined) catch unreachable; const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?; if (field_ty.zigTypeTag(mod) != .NoReturn) break true; } else false @@ -12772,7 +12698,10 @@ fn analyzeSwitchRuntimeBlock( .normal, body, info.capture, - .{ .multi_capture = multi_i }, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + } }), items, .none, false, @@ -12856,7 +12785,10 @@ fn analyzeSwitchRuntimeBlock( .normal, body, info.capture, - .{ .multi_capture = multi_i }, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + } }), items, .none, false, @@ -12921,7 +12853,10 @@ fn analyzeSwitchRuntimeBlock( .special, special.body, special.capture, - .special_capture, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, + } }), &.{item_ref}, item_ref, special.has_tag_capture, @@ -12966,7 +12901,10 @@ fn analyzeSwitchRuntimeBlock( .special, special.body, special.capture, - .special_capture, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, + } }), &.{item_ref}, item_ref, special.has_tag_capture, @@ -12997,7 +12935,10 @@ fn analyzeSwitchRuntimeBlock( .special, special.body, special.capture, - .special_capture, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, + } }), &.{item_ref}, item_ref, special.has_tag_capture, @@ -13025,7 +12966,10 @@ fn analyzeSwitchRuntimeBlock( .special, special.body, special.capture, - .special_capture, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, + } }), &.{.bool_true}, .bool_true, special.has_tag_capture, @@ -13051,7 +12995,10 @@ fn analyzeSwitchRuntimeBlock( .special, special.body, special.capture, - .special_capture, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, + } }), &.{.bool_false}, .bool_false, special.has_tag_capture, @@ -13101,7 +13048,10 @@ fn analyzeSwitchRuntimeBlock( .special, special.body, special.capture, - .special_capture, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, + } }), undefined, // case_vals may be undefined for special prongs .none, false, @@ -13161,6 +13111,7 @@ fn resolveSwitchComptime( cond_operand: Air.Inst.Ref, operand_val: Value, operand_ty: Type, + switch_node_offset: i32, special: SpecialProng, case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), scalar_cases_len: u32, @@ -13181,7 +13132,7 @@ fn resolveSwitchComptime( extra_index += info.body_len; const item = case_vals.items[scalar_i]; - const item_val = sema.resolveConstDefinedValue(child_block, .unneeded, item, undefined) catch unreachable; + const item_val = sema.resolveConstDefinedValue(child_block, LazySrcLoc.unneeded, item, undefined) catch unreachable; if (operand_val.eql(item_val, operand_ty, sema.mod)) { if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_operand); return spa.resolveProngComptime( @@ -13189,7 +13140,10 @@ fn resolveSwitchComptime( .normal, body, info.capture, - .{ .scalar_capture = @intCast(scalar_i) }, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .scalar, .index = @intCast(scalar_i) }, + } }), &.{item}, if (info.is_inline) cond_operand else .none, info.has_tag_capture, @@ -13215,7 +13169,7 @@ fn resolveSwitchComptime( for (items) |item| { // Validation above ensured these will succeed. - const item_val = sema.resolveConstDefinedValue(child_block, .unneeded, item, undefined) catch unreachable; + const item_val = sema.resolveConstDefinedValue(child_block, LazySrcLoc.unneeded, item, undefined) catch unreachable; if (operand_val.eql(item_val, operand_ty, sema.mod)) { if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_operand); return spa.resolveProngComptime( @@ -13223,7 +13177,10 @@ fn resolveSwitchComptime( .normal, body, info.capture, - .{ .multi_capture = @intCast(multi_i) }, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + } }), items, if (info.is_inline) cond_operand else .none, info.has_tag_capture, @@ -13239,8 +13196,8 @@ fn resolveSwitchComptime( case_val_idx += 2; // Validation above ensured these will succeed. - const first_val = sema.resolveConstDefinedValue(child_block, .unneeded, range_items[0], undefined) catch unreachable; - const last_val = sema.resolveConstDefinedValue(child_block, .unneeded, range_items[1], undefined) catch unreachable; + const first_val = sema.resolveConstDefinedValue(child_block, LazySrcLoc.unneeded, range_items[0], undefined) catch unreachable; + const last_val = sema.resolveConstDefinedValue(child_block, LazySrcLoc.unneeded, range_items[1], undefined) catch unreachable; if ((try sema.compareAll(resolved_operand_val, .gte, first_val, operand_ty)) and (try sema.compareAll(resolved_operand_val, .lte, last_val, operand_ty))) { @@ -13250,7 +13207,10 @@ fn resolveSwitchComptime( .normal, body, info.capture, - .{ .multi_capture = @intCast(multi_i) }, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + } }), undefined, // case_vals may be undefined for ranges if (info.is_inline) cond_operand else .none, info.has_tag_capture, @@ -13272,7 +13232,10 @@ fn resolveSwitchComptime( .special, special.body, special.capture, - .special_capture, + child_block.src(.{ .switch_capture = .{ + .switch_node_offset = switch_node_offset, + .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, + } }), undefined, // case_vals may be undefined for special prongs if (special.is_inline) cond_operand else .none, special.has_tag_capture, @@ -13358,36 +13321,19 @@ fn resolveSwitchItemVal( item_ref: Zir.Inst.Ref, /// Coerce `item_ref` to this type. coerce_ty: Type, - switch_node_offset: i32, - switch_prong_src: Module.SwitchProngSrc, - range_expand: Module.SwitchProngSrc.RangeExpand, + item_src: LazySrcLoc, ) CompileError!ResolvedSwitchItem { - const mod = sema.mod; const uncoerced_item = try sema.resolveInst(item_ref); // Constructing a LazySrcLoc is costly because we only have the switch AST node. // Only if we know for sure we need to report a compile error do we resolve the // full source locations. - const item = sema.coerce(block, coerce_ty, uncoerced_item, .unneeded) catch |err| switch (err) { - error.NeededSourceLocation => { - const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand); - _ = try sema.coerce(block, coerce_ty, uncoerced_item, src); - unreachable; - }, - else => |e| return e, - }; + const item = try sema.coerce(block, coerce_ty, uncoerced_item, item_src); - const maybe_lazy = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch |err| switch (err) { - error.NeededSourceLocation => { - const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand); - _ = try sema.resolveConstDefinedValue(block, src, item, .{ - .needed_comptime_reason = "switch prong values must be comptime-known", - }); - unreachable; - }, - else => |e| return e, - }; + const maybe_lazy = try sema.resolveConstDefinedValue(block, item_src, item, .{ + .needed_comptime_reason = "switch prong values must be comptime-known", + }); const val = try sema.resolveLazyValue(maybe_lazy); const new_item = if (val.toIntern() != maybe_lazy.toIntern()) blk: { @@ -13430,8 +13376,11 @@ fn validateErrSetSwitch( seen_errors, item_ref, operand_ty, - src_node_offset, - .{ .scalar = scalar_i }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .scalar, .index = @intCast(scalar_i) }, + .item_idx = .{ .kind = .single, .index = 0 }, + } }), )); } } @@ -13454,8 +13403,11 @@ fn validateErrSetSwitch( seen_errors, item_ref, operand_ty, - src_node_offset, - .{ .multi = .{ .prong = multi_i, .item = @intCast(item_i) } }, + block.src(.{ .switch_case_item = .{ + .switch_node_offset = src_node_offset, + .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, + .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, + } }), )); } @@ -13484,7 +13436,6 @@ fn validateErrSetSwitch( if (!seen_errors.contains(error_name) and !has_else) { const msg = maybe_msg orelse blk: { maybe_msg = try sema.errMsg( - block, src, "switch must handle all possibilities", .{}, @@ -13493,7 +13444,6 @@ fn validateErrSetSwitch( }; try sema.errNote( - block, src, msg, "unhandled error value: 'error.{}'", @@ -13571,18 +13521,24 @@ fn validateSwitchRange( first_ref: Zir.Inst.Ref, last_ref: Zir.Inst.Ref, operand_ty: Type, - src_node_offset: i32, - switch_prong_src: Module.SwitchProngSrc, + item_src: LazySrcLoc, ) CompileError![2]Air.Inst.Ref { const mod = sema.mod; - const first = try sema.resolveSwitchItemVal(block, first_ref, operand_ty, src_node_offset, switch_prong_src, .first); - const last = try sema.resolveSwitchItemVal(block, last_ref, operand_ty, src_node_offset, switch_prong_src, .last); + const first_src: LazySrcLoc = .{ + .base_node_inst = item_src.base_node_inst, + .offset = .{ .switch_case_item_range_first = item_src.offset.switch_case_item }, + }; + const last_src: LazySrcLoc = .{ + .base_node_inst = item_src.base_node_inst, + .offset = .{ .switch_case_item_range_last = item_src.offset.switch_case_item }, + }; + const first = try sema.resolveSwitchItemVal(block, first_ref, operand_ty, first_src); + const last = try sema.resolveSwitchItemVal(block, last_ref, operand_ty, last_src); if (try Value.fromInterned(first.val).compareAll(.gt, Value.fromInterned(last.val), operand_ty, mod)) { - const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), src_node_offset, .first); - return sema.fail(block, src, "range start value is greater than the end value", .{}); + return sema.fail(block, item_src, "range start value is greater than the end value", .{}); } - const maybe_prev_src = try range_set.add(first.val, last.val, switch_prong_src); - try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); + const maybe_prev_src = try range_set.add(first.val, last.val, item_src); + try sema.validateSwitchDupe(block, maybe_prev_src, item_src); return .{ first.ref, last.ref }; } @@ -13592,36 +13548,34 @@ fn validateSwitchItemInt( range_set: *RangeSet, item_ref: Zir.Inst.Ref, operand_ty: Type, - src_node_offset: i32, - switch_prong_src: Module.SwitchProngSrc, + item_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { - const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); - const maybe_prev_src = try range_set.add(item.val, item.val, switch_prong_src); - try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); + const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, item_src); + const maybe_prev_src = try range_set.add(item.val, item.val, item_src); + try sema.validateSwitchDupe(block, maybe_prev_src, item_src); return item.ref; } fn validateSwitchItemEnum( sema: *Sema, block: *Block, - seen_fields: []?Module.SwitchProngSrc, + seen_fields: []?LazySrcLoc, range_set: *RangeSet, item_ref: Zir.Inst.Ref, operand_ty: Type, - src_node_offset: i32, - switch_prong_src: Module.SwitchProngSrc, + item_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { const ip = &sema.mod.intern_pool; - const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); + const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, item_src); const int = ip.indexToKey(item.val).enum_tag.int; const field_index = ip.loadEnumType(ip.typeOf(item.val)).tagValueIndex(ip, int) orelse { - const maybe_prev_src = try range_set.add(int, int, switch_prong_src); - try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); + const maybe_prev_src = try range_set.add(int, int, item_src); + try sema.validateSwitchDupe(block, maybe_prev_src, item_src); return item.ref; }; const maybe_prev_src = seen_fields[field_index]; - seen_fields[field_index] = switch_prong_src; - try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); + seen_fields[field_index] = item_src; + try sema.validateSwitchDupe(block, maybe_prev_src, item_src); return item.ref; } @@ -13631,50 +13585,41 @@ fn validateSwitchItemError( seen_errors: *SwitchErrorSet, item_ref: Zir.Inst.Ref, operand_ty: Type, - src_node_offset: i32, - switch_prong_src: Module.SwitchProngSrc, + item_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { const ip = &sema.mod.intern_pool; - const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); + const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, item_src); const error_name = ip.indexToKey(item.val).err.name; - const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev| + const maybe_prev_src = if (try seen_errors.fetchPut(error_name, item_src)) |prev| prev.value else null; - try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); + try sema.validateSwitchDupe(block, maybe_prev_src, item_src); return item.ref; } fn validateSwitchDupe( sema: *Sema, block: *Block, - maybe_prev_src: ?Module.SwitchProngSrc, - switch_prong_src: Module.SwitchProngSrc, - src_node_offset: i32, + maybe_prev_src: ?LazySrcLoc, + item_src: LazySrcLoc, ) CompileError!void { - const prev_prong_src = maybe_prev_src orelse return; - const mod = sema.mod; - const block_src_decl = mod.declPtr(block.src_decl); - const src = switch_prong_src.resolve(mod, block_src_decl, src_node_offset, .none); - const prev_src = prev_prong_src.resolve(mod, block_src_decl, src_node_offset, .none); - const msg = msg: { + const prev_item_src = maybe_prev_src orelse return; + return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg( - block, - src, + item_src, "duplicate switch value", .{}, ); errdefer msg.destroy(sema.gpa); try sema.errNote( - block, - prev_src, + prev_item_src, msg, "previous value here", .{}, ); break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + }); } fn validateSwitchItemBool( @@ -13683,25 +13628,21 @@ fn validateSwitchItemBool( true_count: *u8, false_count: *u8, item_ref: Zir.Inst.Ref, - src_node_offset: i32, - switch_prong_src: Module.SwitchProngSrc, + item_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { - const mod = sema.mod; - const item = try sema.resolveSwitchItemVal(block, item_ref, Type.bool, src_node_offset, switch_prong_src, .none); + const item = try sema.resolveSwitchItemVal(block, item_ref, Type.bool, item_src); if (Value.fromInterned(item.val).toBool()) { true_count.* += 1; } else { false_count.* += 1; } if (true_count.* > 1 or false_count.* > 1) { - const block_src_decl = sema.mod.declPtr(block.src_decl); - const src = switch_prong_src.resolve(mod, block_src_decl, src_node_offset, .none); - return sema.fail(block, src, "duplicate switch value", .{}); + return sema.fail(block, item_src, "duplicate switch value", .{}); } return item.ref; } -const ValueSrcMap = std.AutoHashMapUnmanaged(InternPool.Index, Module.SwitchProngSrc); +const ValueSrcMap = std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc); fn validateSwitchItemSparse( sema: *Sema, @@ -13709,12 +13650,11 @@ fn validateSwitchItemSparse( seen_values: *ValueSrcMap, item_ref: Zir.Inst.Ref, operand_ty: Type, - src_node_offset: i32, - switch_prong_src: Module.SwitchProngSrc, + item_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { - const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none); - const kv = (try seen_values.fetchPut(sema.gpa, item.val, switch_prong_src)) orelse return item.ref; - try sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset); + const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, item_src); + const kv = try seen_values.fetchPut(sema.gpa, item.val, item_src) orelse return item.ref; + try sema.validateSwitchDupe(block, kv.value, item_src); unreachable; } @@ -13728,19 +13668,17 @@ fn validateSwitchNoRange( if (ranges_len == 0) return; - const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = src_node_offset }; - const range_src: LazySrcLoc = .{ .node_offset_switch_range = src_node_offset }; + const operand_src = block.src(.{ .node_offset_switch_operand = src_node_offset }); + const range_src = block.src(.{ .node_offset_switch_range = src_node_offset }); const msg = msg: { const msg = try sema.errMsg( - block, operand_src, "ranges not allowed when switching on type '{}'", .{operand_ty.fmt(sema.mod)}, ); errdefer msg.destroy(sema.gpa); try sema.errNote( - block, range_src, msg, "range here", @@ -13867,8 +13805,8 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const ty = try sema.resolveType(block, ty_src, extra.lhs); const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, .{ .needed_comptime_reason = "field name must be comptime-known", @@ -13919,8 +13857,8 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); const container_type = try sema.resolveType(block, lhs_src, extra.lhs); const decl_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, .{ .needed_comptime_reason = "decl name must be comptime-known", @@ -13979,7 +13917,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const name = try sema.resolveConstString(block, operand_src, inst_data.operand, .{ .needed_comptime_reason = "file path name must be comptime-known", }); @@ -13988,8 +13926,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A return sema.fail(block, operand_src, "file path name cannot be empty", .{}); } - const src_loc = mod.declPtr(block.src_decl).toSrcLoc(operand_src, mod); - const val = mod.embedFile(block.getFileScope(mod), name, src_loc) catch |err| switch (err) { + const val = mod.embedFile(block.getFileScope(mod), name, operand_src.upgrade(mod)) catch |err| switch (err) { error.ImportOutsideModulePath => { return sema.fail(block, operand_src, "embed of file outside package path: '{s}'", .{name}); }, @@ -14031,8 +13968,8 @@ fn zirShl( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -14201,8 +14138,8 @@ fn zirShr( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -14335,9 +14272,9 @@ fn zirBitwise( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -14390,7 +14327,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; + const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); const operand = try sema.resolveInst(inst_data.operand); const operand_type = sema.typeOf(operand); @@ -14436,7 +14373,7 @@ fn analyzeTupleCat( const mod = sema.mod; const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); - const src = LazySrcLoc.nodeOffset(src_node); + const src = block.nodeOffset(src_node); const lhs_len = lhs_ty.structFieldCount(mod); const rhs_len = rhs_ty.structFieldCount(mod); @@ -14463,10 +14400,10 @@ fn analyzeTupleCat( types[i] = lhs_ty.structFieldType(i, mod).toIntern(); const default_val = lhs_ty.structFieldDefaultValue(i, mod); values[i] = default_val.toIntern(); - const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{ + const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = src_node, .elem_index = i, - } }; + } }); if (default_val.toIntern() == .unreachable_value) { runtime_src = operand_src; values[i] = .none; @@ -14477,10 +14414,10 @@ fn analyzeTupleCat( types[i + lhs_len] = rhs_ty.structFieldType(i, mod).toIntern(); const default_val = rhs_ty.structFieldDefaultValue(i, mod); values[i + lhs_len] = default_val.toIntern(); - const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{ + const operand_src = block.src(.{ .array_cat_rhs = .{ .array_cat_offset = src_node, .elem_index = i, - } }; + } }); if (default_val.toIntern() == .unreachable_value) { runtime_src = operand_src; values[i + lhs_len] = .none; @@ -14508,18 +14445,18 @@ fn analyzeTupleCat( const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len); var i: u32 = 0; while (i < lhs_len) : (i += 1) { - const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{ + const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = src_node, .elem_index = i, - } }; + } }); element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, i, lhs_ty); } i = 0; while (i < rhs_len) : (i += 1) { - const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{ + const operand_src = block.src(.{ .array_cat_rhs = .{ .array_cat_offset = src_node, .elem_index = i, - } }; + } }); element_refs[i + lhs_len] = try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty); } @@ -14546,8 +14483,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); } - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: { if (lhs_is_tuple) break :lhs_info @as(Type.ArrayInfo, undefined); @@ -14659,10 +14596,10 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable"; const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val; const elem_val_inst = Air.internedToRef(elem_val.toIntern()); - const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{ + const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = inst_data.src_node, .elem_index = elem_i, - } }; + } }); const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined); element_vals[elem_i] = coerced_elem_val.toIntern(); @@ -14672,10 +14609,10 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable"; const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val; const elem_val_inst = Air.internedToRef(elem_val.toIntern()); - const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{ + const operand_src = block.src(.{ .array_cat_rhs = .{ .array_cat_offset = inst_data.src_node, .elem_index = @intCast(rhs_elem_i), - } }; + } }); const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined); element_vals[elem_i] = coerced_elem_val.toIntern(); @@ -14704,10 +14641,10 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai while (elem_i < lhs_len) : (elem_i += 1) { const elem_index = try mod.intRef(Type.usize, elem_i); const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); - const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{ + const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = inst_data.src_node, .elem_index = elem_i, - } }; + } }); const init = try sema.elemVal(block, operand_src, lhs, elem_index, src, true); try sema.storePtr2(block, src, elem_ptr, src, init, operand_src, .store); } @@ -14716,10 +14653,10 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const elem_index = try mod.intRef(Type.usize, elem_i); const rhs_index = try mod.intRef(Type.usize, rhs_elem_i); const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); - const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{ + const operand_src = block.src(.{ .array_cat_rhs = .{ .array_cat_offset = inst_data.src_node, .elem_index = @intCast(rhs_elem_i), - } }; + } }); const init = try sema.elemVal(block, operand_src, rhs, rhs_index, src, true); try sema.storePtr2(block, src, elem_ptr, src, init, operand_src, .store); } @@ -14738,20 +14675,20 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai var elem_i: u32 = 0; while (elem_i < lhs_len) : (elem_i += 1) { const index = try mod.intRef(Type.usize, elem_i); - const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{ + const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = inst_data.src_node, .elem_index = elem_i, - } }; + } }); const init = try sema.elemVal(block, operand_src, lhs, index, src, true); element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, operand_src); } while (elem_i < result_len) : (elem_i += 1) { const rhs_elem_i = elem_i - lhs_len; const index = try mod.intRef(Type.usize, rhs_elem_i); - const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{ + const operand_src = block.src(.{ .array_cat_rhs = .{ .array_cat_offset = inst_data.src_node, .elem_index = @intCast(rhs_elem_i), - } }; + } }); const init = try sema.elemVal(block, operand_src, rhs, index, src, true); element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, operand_src); } @@ -14813,8 +14750,8 @@ fn analyzeTupleMul( ) CompileError!Air.Inst.Ref { const mod = sema.mod; const operand_ty = sema.typeOf(operand); - const src = LazySrcLoc.nodeOffset(src_node); - const len_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node }; + const src = block.nodeOffset(src_node); + const len_src = block.src(.{ .node_offset_bin_rhs = src_node }); const tuple_len = operand_ty.structFieldCount(mod); const final_len = std.math.mul(usize, tuple_len, factor) catch @@ -14831,10 +14768,10 @@ fn analyzeTupleMul( for (0..tuple_len) |i| { types[i] = operand_ty.structFieldType(i, mod).toIntern(); values[i] = operand_ty.structFieldDefaultValue(i, mod).toIntern(); - const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{ + const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = src_node, .elem_index = @intCast(i), - } }; + } }); if (values[i] == .unreachable_value) { runtime_src = operand_src; values[i] = .none; // TODO don't treat unreachable_value as special @@ -14866,10 +14803,10 @@ fn analyzeTupleMul( const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len); var i: u32 = 0; while (i < tuple_len) : (i += 1) { - const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{ + const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = src_node, .elem_index = i, - } }; + } }); element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(i), operand_ty); } i = 1; @@ -14890,9 +14827,9 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const uncoerced_lhs = try sema.resolveInst(extra.lhs); const uncoerced_lhs_ty = sema.typeOf(uncoerced_lhs); const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const operator_src = block.src(.{ .node_offset_main_token = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const lhs, const lhs_ty = coerced_lhs: { // If we have a result type, we might be able to do this more efficiently @@ -14941,11 +14878,11 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai // Analyze the lhs first, to catch the case that someone tried to do exponentiation const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse { const msg = msg: { - const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(mod)}); + const msg = try sema.errMsg(lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); switch (lhs_ty.zigTypeTag(mod)) { .Int, .Float, .ComptimeFloat, .ComptimeInt, .Vector => { - try sema.errNote(block, operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{}); + try sema.errNote(operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{}); }, else => {}, } @@ -15061,7 +14998,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const lhs_src = src; - const rhs_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; + const rhs_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); const rhs = try sema.resolveInst(inst_data.operand); const rhs_ty = sema.typeOf(rhs); @@ -15093,7 +15030,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const lhs_src = src; - const rhs_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; + const rhs_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); const rhs = try sema.resolveInst(inst_data.operand); const rhs_ty = sema.typeOf(rhs); @@ -15119,9 +15056,9 @@ fn zirArithmetic( defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -15132,9 +15069,9 @@ fn zirArithmetic( fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -15297,9 +15234,9 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -15462,9 +15399,9 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -15572,9 +15509,9 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -15813,9 +15750,9 @@ fn airTag(block: *Block, is_int: bool, normal: Air.Inst.Tag, optimized: Air.Inst fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -15997,9 +15934,9 @@ fn intRemScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) CompileErr fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -16092,9 +16029,9 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -16194,10 +16131,10 @@ fn zirOverflowArithmetic( defer tracy.end(); const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); + const src = block.nodeOffset(extra.node); - const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; + const lhs_src = block.builtinCallArgSrc(extra.node, 0); + const rhs_src = block.builtinCallArgSrc(extra.node, 1); const uncasted_lhs = try sema.resolveInst(extra.lhs); const uncasted_rhs = try sema.resolveInst(extra.rhs); @@ -17025,8 +16962,8 @@ fn zirAsm( defer tracy.end(); const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand); - const src = LazySrcLoc.nodeOffset(extra.data.src_node); - const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = extra.data.src_node }; + const src = block.nodeOffset(extra.data.src_node); + const ret_ty_src = block.src(.{ .node_offset_asm_ret_ty = extra.data.src_node }); const outputs_len: u5 = @truncate(extended.small); const inputs_len: u5 = @truncate(extended.small >> 5); const clobbers_len: u5 = @truncate(extended.small >> 10); @@ -17200,8 +17137,8 @@ fn zirCmpEq( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); @@ -17280,9 +17217,9 @@ fn analyzeCmpUnionTag( try sema.resolveTypeFields(union_ty); const union_tag_ty = union_ty.unionTagType(mod) orelse { const msg = msg: { - const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); + const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); errdefer msg.destroy(sema.gpa); - try mod.errNoteNonLazy(union_ty.declSrcLoc(mod), msg, "union '{}' is not a tagged union", .{union_ty.fmt(mod)}); + try sema.errNote(union_ty.srcLoc(mod), msg, "union '{}' is not a tagged union", .{union_ty.fmt(mod)}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -17316,8 +17253,8 @@ fn zirCmp( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); return sema.analyzeCmp(block, src, lhs, rhs, op, lhs_src, rhs_src, false); @@ -17459,7 +17396,7 @@ fn runtimeBoolCmp( fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, operand_src, inst_data.operand); switch (ty.zigTypeTag(mod)) { .Fn, @@ -17502,7 +17439,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); switch (operand_ty.zigTypeTag(mod)) { .Fn, @@ -17546,7 +17483,7 @@ fn zirThis( ) CompileError!Air.Inst.Ref { const mod = sema.mod; const this_decl_index = mod.namespacePtr(block.namespace).decl_index; - const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand)); + const src = block.nodeOffset(@bitCast(extended.operand)); return sema.analyzeDeclVal(block, src, this_decl_index); } @@ -17556,7 +17493,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat const captures = mod.namespacePtr(block.namespace).getType(mod).getCaptures(mod); const src_node: i32 = @bitCast(extended.operand); - const src = LazySrcLoc.nodeOffset(src_node); + const src = block.nodeOffset(src_node); const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) { .@"comptime" => |index| return Air.internedToRef(index), @@ -17570,7 +17507,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat if (!block.is_typeof and sema.func_index == .none) { const msg = msg: { const name = name: { - const file = sema.owner_decl.getFileScope(mod); + // 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 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}", .{ @@ -17578,15 +17516,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat }); break :name null; }; - const node = sema.owner_decl.relativeToNodeIndex(src_node); + const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node))); const token = tree.nodes.items(.main_token)[node]; break :name tree.tokenSlice(token); }; const msg = if (name) |some| - try sema.errMsg(block, src, "'{s}' not accessible outside function scope", .{some}) + try sema.errMsg(src, "'{s}' not accessible outside function scope", .{some}) else - try sema.errMsg(block, src, "variable not accessible outside function scope", .{}); + try sema.errMsg(src, "variable not accessible outside function scope", .{}); errdefer msg.destroy(sema.gpa); // TODO add "declared here" note @@ -17598,7 +17536,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 = sema.owner_decl.getFileScope(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}", .{ @@ -17606,18 +17544,18 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat }); break :name null; }; - const node = sema.owner_decl.relativeToNodeIndex(src_node); + const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node))); const token = tree.nodes.items(.main_token)[node]; break :name tree.tokenSlice(token); }; const msg = if (name) |some| - try sema.errMsg(block, src, "'{s}' not accessible from inner function", .{some}) + try sema.errMsg(src, "'{s}' not accessible from inner function", .{some}) else - try sema.errMsg(block, src, "variable not accessible from inner function", .{}); + try sema.errMsg(src, "variable not accessible from inner function", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, LazySrcLoc.nodeOffset(0), msg, "crossed function definition here", .{}); + try sema.errNote(block.nodeOffset(0), msg, "crossed function definition here", .{}); // TODO add "declared here" note break :msg msg; @@ -17649,7 +17587,7 @@ fn zirFrameAddress( block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { - const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand)); + const src = block.nodeOffset(@bitCast(extended.operand)); try sema.requireRuntimeBlock(block, src, null); return try block.addNoOp(.frame_addr); } @@ -18913,6 +18851,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr .is_typeof = true, .want_safety = false, .error_return_trace_index = block.error_return_trace_index, + .src_base_inst = block.src_base_inst, }; defer child_block.instructions.deinit(sema.gpa); @@ -18977,7 +18916,7 @@ fn zirTypeofPeer( defer tracy.end(); const extra = sema.code.extraData(Zir.Inst.TypeOfPeer, extended.operand); - const src = LazySrcLoc.nodeOffset(extra.data.src_node); + const src = block.nodeOffset(extra.data.src_node); const body = sema.code.bodySlice(extra.data.body_index, extra.data.body_len); var child_block: Block = .{ @@ -18992,6 +18931,7 @@ fn zirTypeofPeer( .runtime_cond = block.runtime_cond, .runtime_loop = block.runtime_loop, .runtime_index = block.runtime_index, + .src_base_inst = block.src_base_inst, }; defer child_block.instructions.deinit(sema.gpa); // Ignore the result, we only care about the instructions in `args`. @@ -19017,7 +18957,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; + const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); const uncasted_operand = try sema.resolveInst(inst_data.operand); const operand = try sema.coerce(block, Type.bool, uncasted_operand, operand_src); @@ -19048,8 +18988,8 @@ fn zirBoolBr( const uncoerced_lhs = try sema.resolveInst(extra.data.lhs); const body = sema.code.bodySlice(extra.end, extra.data.body_len); - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const lhs_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = parent_block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const lhs = try sema.coerce(parent_block, Type.bool, uncoerced_lhs, lhs_src); @@ -19080,7 +19020,7 @@ fn zirBoolBr( var child_block = parent_block.makeSubBlock(); child_block.runtime_loop = null; - child_block.runtime_cond = mod.declPtr(child_block.src_decl).toSrcLoc(lhs_src, mod); + child_block.runtime_cond = lhs_src; child_block.runtime_index.increment(); defer child_block.instructions.deinit(gpa); @@ -19253,7 +19193,7 @@ fn zirCondbr( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node }; + const cond_src = parent_block.src(.{ .node_offset_if_cond = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len); @@ -19276,7 +19216,7 @@ fn zirCondbr( // instructions array in between using it for the then block and else block. var sub_block = parent_block.makeSubBlock(); sub_block.runtime_loop = null; - sub_block.runtime_cond = mod.declPtr(parent_block.src_decl).toSrcLoc(cond_src, mod); + sub_block.runtime_cond = cond_src; sub_block.runtime_index.increment(); sub_block.need_debug_scope = null; // this body is emitted regardless defer sub_block.instructions.deinit(gpa); @@ -19321,7 +19261,7 @@ fn zirCondbr( fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = parent_block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; + const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const body = sema.code.bodySlice(extra.end, extra.data.body_len); const err_union = try sema.resolveInst(extra.data.operand); @@ -19368,7 +19308,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = parent_block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; + const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const body = sema.code.bodySlice(extra.end, extra.data.body_len); const operand = try sema.resolveInst(extra.data.operand); @@ -19464,6 +19404,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label .label = &labeled_block.label, .inlining = block.inlining, .is_comptime = block.is_comptime, + .src_base_inst = block.src_base_inst, }, }; sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block); @@ -19498,11 +19439,11 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError return sema.fail(block, src, "reached unreachable code", .{}); } // TODO Add compile error for @optimizeFor occurring too late in a scope. - block.addUnreachable(src, true) catch |err| switch (err) { + sema.analyzeUnreachable(block, src, true) catch |err| switch (err) { error.AnalysisFail => { const msg = sema.err orelse return err; if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err; - try sema.errNote(block, src, msg, "the end of a naked function is implicitly unreachable", .{}); + try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{}); return err; }, else => |e| return e, @@ -19549,31 +19490,31 @@ fn zirRetImplicit( // Calling a safety function from a naked function would not be legal. _ = try block.addNoOp(.trap); } else { - try block.addUnreachable(r_brace_src, false); + try sema.analyzeUnreachable(block, r_brace_src, false); } return; } const operand = try sema.resolveInst(inst_data.operand); - const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; + const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = 0 }); const base_tag = sema.fn_ret_ty.baseZigTypeTag(mod); if (base_tag == .NoReturn) { const msg = msg: { - const msg = try sema.errMsg(block, ret_ty_src, "function declared '{}' implicitly returns", .{ + const msg = try sema.errMsg(ret_ty_src, "function declared '{}' implicitly returns", .{ sema.fn_ret_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); + try sema.errNote(r_brace_src, msg, "control flow reaches end of body here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); } else if (base_tag != .Void) { const msg = msg: { - const msg = try sema.errMsg(block, ret_ty_src, "function with non-void return type '{}' implicitly returns", .{ + const msg = try sema.errMsg(ret_ty_src, "function with non-void return type '{}' implicitly returns", .{ sema.fn_ret_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); + try sema.errNote(r_brace_src, msg, "control flow reaches end of body here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -19590,7 +19531,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi const operand = try sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); - return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node }); + return sema.analyzeRet(block, operand, src, block.src(.{ .node_offset_return_operand = inst_data.src_node })); } fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { @@ -19603,7 +19544,7 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi if (block.is_comptime or block.inlining != null or sema.func_is_naked) { const operand = try sema.analyzeLoad(block, src, ret_ptr, src); - return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node }); + return sema.analyzeRet(block, operand, src, block.src(.{ .node_offset_return_operand = inst_data.src_node })); } if (sema.wantErrorReturnTracing(sema.fn_ret_ty)) { @@ -19816,9 +19757,7 @@ fn analyzeRet( inlining.comptime_result = operand; if (sema.fn_ret_ty.isError(mod) and ret_val.getErrorName(mod) != .none) { - const src_decl = mod.declPtr(block.src_decl); - const src_loc = src_decl.toSrcLoc(src, mod); - try sema.comptime_err_ret_trace.append(src_loc); + try sema.comptime_err_ret_trace.append(src); } return error.ComptimeReturn; } @@ -19832,10 +19771,10 @@ fn analyzeRet( return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{}); } else if (sema.func_is_naked) { const msg = msg: { - const msg = try sema.errMsg(block, src, "cannot return from naked function", .{}); + const msg = try sema.errMsg(src, "cannot return from naked function", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "can only return using assembly", .{}); + try sema.errNote(src, msg, "can only return using assembly", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -19871,18 +19810,18 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type; const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index); - const elem_ty_src: LazySrcLoc = .{ .node_offset_ptr_elem = extra.data.src_node }; - const sentinel_src: LazySrcLoc = .{ .node_offset_ptr_sentinel = extra.data.src_node }; - const align_src: LazySrcLoc = .{ .node_offset_ptr_align = extra.data.src_node }; - const addrspace_src: LazySrcLoc = .{ .node_offset_ptr_addrspace = extra.data.src_node }; - const bitoffset_src: LazySrcLoc = .{ .node_offset_ptr_bitoffset = extra.data.src_node }; - const hostsize_src: LazySrcLoc = .{ .node_offset_ptr_hostsize = extra.data.src_node }; + const elem_ty_src = block.src(.{ .node_offset_ptr_elem = extra.data.src_node }); + const sentinel_src = block.src(.{ .node_offset_ptr_sentinel = extra.data.src_node }); + const align_src = block.src(.{ .node_offset_ptr_align = extra.data.src_node }); + const addrspace_src = block.src(.{ .node_offset_ptr_addrspace = extra.data.src_node }); + const bitoffset_src = block.src(.{ .node_offset_ptr_bitoffset = extra.data.src_node }); + const hostsize_src = block.src(.{ .node_offset_ptr_hostsize = extra.data.src_node }); const elem_ty = blk: { const air_inst = try sema.resolveInst(extra.data.elem_type); const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| { if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(mod)) { - try sema.errNote(block, elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{}); + try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{}); } return err; }; @@ -19974,11 +19913,10 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } else if (inst_data.size == .C) { if (!try sema.validateExternType(elem_ty, .other)) { const msg = msg: { - const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(mod)}); + const msg = try sema.errMsg(elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(elem_ty_src, mod), elem_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other); try sema.addDeclaredHereNote(msg, elem_ty); break :msg msg; @@ -19992,10 +19930,9 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air if (host_size != 0 and !try sema.validatePackedType(elem_ty)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, elem_ty_src, "bit-pointer cannot refer to value of type '{}'", .{elem_ty.fmt(mod)}); + const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{}'", .{elem_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotPacked(msg, src_decl.toSrcLoc(elem_ty_src, mod), elem_ty); + try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty); break :msg msg; }); } @@ -20025,7 +19962,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node }; + const ty_src = block.src(.{ .node_offset_init_ty = inst_data.src_node }); const obj_ty = try sema.resolveType(block, ty_src, inst_data.operand); const mod = sema.mod; @@ -20119,9 +20056,9 @@ fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) Com fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const field_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; - const init_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; + const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const field_src = block.builtinCallArgSrc(inst_data.src_node, 1); + const init_src = block.builtinCallArgSrc(inst_data.src_node, 2); const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; const union_ty = try sema.resolveType(block, ty_src, extra.union_type); if (union_ty.zigTypeTag(sema.mod) != .Union) { @@ -20215,7 +20152,7 @@ fn zirStructInit( extra_index = item.end; const field_type_data = zir_datas[@intFromEnum(item.data.field_type)].pl_node; - const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node }; + const field_src = block.src(.{ .node_offset_initializer = field_type_data.src_node }); const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; const field_name = try ip.getOrPutString( gpa, @@ -20256,7 +20193,7 @@ fn zirStructInit( const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end); const field_type_data = zir_datas[@intFromEnum(item.data.field_type)].pl_node; - const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node }; + const field_src = block.src(.{ .node_offset_initializer = field_type_data.src_node }); const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; const field_name = try ip.getOrPutString( gpa, @@ -20270,7 +20207,7 @@ fn zirStructInit( if (field_ty.zigTypeTag(mod) == .NoReturn) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{}); + const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{}); errdefer msg.destroy(sema.gpa); try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{}' declared here", .{ @@ -20348,16 +20285,12 @@ fn finishStructInit( for (0..anon_struct.types.len) |i| { if (field_inits[i] != .none) { // Coerce the init value to the field type. + const field_src = block.src(.{ .init_elem = .{ + .init_node_offset = init_src.offset.node_offset.x, + .elem_index = @intCast(i), + } }); const field_ty = Type.fromInterned(anon_struct.types.get(ip)[i]); - field_inits[i] = sema.coerce(block, field_ty, field_inits[i], .unneeded) catch |err| switch (err) { - error.NeededSourceLocation => { - const decl = mod.declPtr(block.src_decl); - const field_src = mod.initSrc(init_src.node_offset.x, decl, i); - _ = try sema.coerce(block, field_ty, field_inits[i], field_src); - unreachable; - }, - else => |e| return e, - }; + field_inits[i] = try sema.coerce(block, field_ty, field_inits[i], field_src); continue; } @@ -20367,18 +20300,18 @@ fn finishStructInit( if (anon_struct.names.len == 0) { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, .{i}); + try sema.errNote(init_src, msg, template, .{i}); } else { - root_msg = try sema.errMsg(block, init_src, template, .{i}); + root_msg = try sema.errMsg(init_src, template, .{i}); } } else { const field_name = anon_struct.names.get(ip)[i]; const template = "missing struct field: {}"; const args = .{field_name.fmt(ip)}; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, args); + try sema.errNote(init_src, msg, template, args); } else { - root_msg = try sema.errMsg(block, init_src, template, args); + root_msg = try sema.errMsg(init_src, template, args); } } } else { @@ -20391,16 +20324,12 @@ fn finishStructInit( for (0..struct_type.field_types.len) |i| { if (field_inits[i] != .none) { // Coerce the init value to the field type. + const field_src = block.src(.{ .init_elem = .{ + .init_node_offset = init_src.offset.node_offset.x, + .elem_index = @intCast(i), + } }); const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); - field_inits[i] = sema.coerce(block, field_ty, field_inits[i], init_src) catch |err| switch (err) { - error.NeededSourceLocation => { - const decl = mod.declPtr(block.src_decl); - const field_src = mod.initSrc(init_src.node_offset.x, decl, i); - _ = try sema.coerce(block, field_ty, field_inits[i], field_src); - unreachable; - }, - else => |e| return e, - }; + field_inits[i] = try sema.coerce(block, field_ty, field_inits[i], field_src); continue; } @@ -20413,16 +20342,16 @@ fn finishStructInit( const template = "missing struct field: {}"; const args = .{field_name.fmt(ip)}; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, args); + try sema.errNote(init_src, msg, template, args); } else { - root_msg = try sema.errMsg(block, init_src, template, args); + root_msg = try sema.errMsg(init_src, template, args); } } else { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { - try sema.errNote(block, init_src, msg, template, .{i}); + try sema.errNote(init_src, msg, template, .{i}); } else { - root_msg = try sema.errMsg(block, init_src, template, .{i}); + root_msg = try sema.errMsg(init_src, template, .{i}); } } } else { @@ -20434,16 +20363,7 @@ fn finishStructInit( } if (root_msg) |msg| { - if (mod.typeToStruct(struct_ty)) |struct_type| { - const decl = mod.declPtr(struct_type.decl.unwrap().?); - const fqn = try decl.fullyQualifiedName(mod); - try mod.errNoteNonLazy( - decl.srcLoc(mod), - msg, - "struct '{}' declared here", - .{fqn.fmt(ip)}, - ); - } + try sema.addDeclaredHereNote(msg, struct_ty); root_msg = null; return sema.failWithOwnedErrorMsg(block, msg); } @@ -20470,9 +20390,10 @@ fn finishStructInit( }; if (try sema.typeRequiresComptime(struct_ty)) { - const decl = mod.declPtr(block.src_decl); - const field_src = mod.initSrc(init_src.node_offset.x, decl, runtime_index); - return sema.failWithNeededComptime(block, field_src, .{ + return sema.failWithNeededComptime(block, block.src(.{ .init_elem = .{ + .init_node_offset = init_src.offset.node_offset.x, + .elem_index = @intCast(runtime_index), + } }), .{ .needed_comptime_reason = "initializer of comptime only struct must be comptime-known", }); } @@ -20500,15 +20421,10 @@ fn finishStructInit( return sema.makePtrConst(block, alloc); } - sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) { - error.NeededSourceLocation => { - const decl = mod.declPtr(block.src_decl); - const field_src = mod.initSrc(dest_src.node_offset.x, decl, runtime_index); - try sema.requireRuntimeBlock(block, dest_src, field_src); - unreachable; - }, - else => |e| return e, - }; + try sema.requireRuntimeBlock(block, dest_src, block.src(.{ .init_elem = .{ + .init_node_offset = init_src.offset.node_offset.x, + .elem_index = @intCast(runtime_index), + } })); try sema.resolveStructFieldInits(struct_ty); try sema.queueFullTypeResolution(struct_ty); const struct_val = try block.addAggregateInit(struct_ty, field_inits); @@ -20576,9 +20492,11 @@ fn structInitAnon( field_ty.* = sema.typeOf(init).toIntern(); if (Type.fromInterned(field_ty.*).zigTypeTag(mod) == .Opaque) { const msg = msg: { - const decl = mod.declPtr(block.src_decl); - const field_src = mod.initSrc(src.node_offset.x, decl, @intCast(i_usize)); - const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); + const field_src = block.src(.{ .init_elem = .{ + .init_node_offset = src.offset.node_offset.x, + .elem_index = @intCast(i_usize), + } }); + const msg = try sema.errMsg(field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); errdefer msg.destroy(sema.gpa); try sema.addDeclaredHereNote(msg, Type.fromInterned(field_ty.*)); @@ -20610,15 +20528,10 @@ fn structInitAnon( return sema.addConstantMaybeRef(tuple_val, is_ref); }; - sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) { - error.NeededSourceLocation => { - const decl = mod.declPtr(block.src_decl); - const field_src = mod.initSrc(src.node_offset.x, decl, runtime_index); - try sema.requireRuntimeBlock(block, src, field_src); - unreachable; - }, - else => |e| return e, - }; + try sema.requireRuntimeBlock(block, LazySrcLoc.unneeded, block.src(.{ .init_elem = .{ + .init_node_offset = src.offset.node_offset.x, + .elem_index = @intCast(runtime_index), + } })); if (is_ref) { const target = mod.getTarget(); @@ -20697,15 +20610,19 @@ fn zirArrayInit( const resolved_args = try gpa.alloc(Air.Inst.Ref, final_len); defer gpa.free(resolved_args); for (resolved_args, 0..) |*dest, i| { + const elem_src = block.src(.{ .init_elem = .{ + .init_node_offset = src.offset.node_offset.x, + .elem_index = @intCast(i), + } }); // Less inits than needed. if (i + 2 > args.len) if (is_tuple) { const default_val = array_ty.structFieldDefaultValue(i, mod).toIntern(); if (default_val == .unreachable_value) { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { - try sema.errNote(block, src, msg, template, .{i}); + try sema.errNote(src, msg, template, .{i}); } else { - root_msg = try sema.errMsg(block, src, template, .{i}); + root_msg = try sema.errMsg(src, template, .{i}); } } else { dest.* = Air.internedToRef(default_val); @@ -20722,29 +20639,17 @@ fn zirArrayInit( array_ty.structFieldType(i, mod) else array_ty.elemType2(mod); - dest.* = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) { - error.NeededSourceLocation => { - const decl = mod.declPtr(block.src_decl); - const elem_src = mod.initSrc(src.node_offset.x, decl, i); - _ = try sema.coerce(block, elem_ty, resolved_arg, elem_src); - unreachable; - }, - else => return err, - }; + dest.* = try sema.coerce(block, elem_ty, resolved_arg, elem_src); if (is_tuple) { if (array_ty.structFieldIsComptime(i, mod)) try sema.resolveStructFieldInits(array_ty); if (try array_ty.structFieldValueComptime(mod, i)) |field_val| { const init_val = try sema.resolveValue(dest.*) orelse { - const decl = mod.declPtr(block.src_decl); - const elem_src = mod.initSrc(src.node_offset.x, decl, i); return sema.failWithNeededComptime(block, elem_src, .{ .needed_comptime_reason = "value stored in comptime field must be comptime-known", }); }; if (!field_val.eql(init_val, elem_ty, mod)) { - const decl = mod.declPtr(block.src_decl); - const elem_src = mod.initSrc(src.node_offset.x, decl, i); return sema.failWithInvalidComptimeFieldStore(block, elem_src, array_ty, i); } } @@ -20777,15 +20682,10 @@ fn zirArrayInit( return sema.addConstantMaybeRef(result_val.toIntern(), is_ref); }; - sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) { - error.NeededSourceLocation => { - const decl = mod.declPtr(block.src_decl); - const elem_src = mod.initSrc(src.node_offset.x, decl, runtime_index); - try sema.requireRuntimeBlock(block, src, elem_src); - unreachable; - }, - else => return err, - }; + try sema.requireRuntimeBlock(block, LazySrcLoc.unneeded, block.src(.{ .init_elem = .{ + .init_node_offset = src.offset.node_offset.x, + .elem_index = runtime_index, + } })); try sema.queueFullTypeResolution(array_ty); if (is_ref) { @@ -20864,7 +20764,7 @@ fn arrayInitAnon( types[i] = sema.typeOf(elem).toIntern(); if (Type.fromInterned(types[i]).zigTypeTag(mod) == .Opaque) { const msg = msg: { - const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); + const msg = try sema.errMsg(operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); errdefer msg.destroy(gpa); try sema.addDeclaredHereNote(msg, Type.fromInterned(types[i])); @@ -20935,8 +20835,8 @@ fn addConstantMaybeRef(sema: *Sema, val: InternPool.Index, is_ref: bool) !Air.In fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data; - const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const field_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const field_src = block.builtinCallArgSrc(inst_data.src_node, 1); const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type); const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .needed_comptime_reason = "field name must be comptime-known", @@ -20950,7 +20850,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; const ty_src = block.nodeOffset(inst_data.src_node); - const field_name_src: LazySrcLoc = .{ .node_offset_field_name_init = inst_data.src_node }; + const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node }); const wrapped_aggregate_ty = sema.resolveType(block, ty_src, extra.container_type) catch |err| switch (err) { // Since this is a ZIR instruction that returns a type, encountering // generic poison should not result in a failed compilation, but the @@ -20990,7 +20890,7 @@ fn fieldType( .struct_type => { const struct_type = ip.loadStructType(cur_ty.toIntern()); const field_index = struct_type.nameIndex(ip, field_name) orelse - return sema.failWithBadStructFieldAccess(block, struct_type, field_src, field_name); + return sema.failWithBadStructFieldAccess(block, cur_ty, struct_type, field_src, field_name); const field_ty = struct_type.field_types.get(ip)[field_index]; return Air.internedToRef(field_ty); }, @@ -20999,7 +20899,7 @@ fn fieldType( .Union => { const union_obj = mod.typeToUnion(cur_ty).?; const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse - return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); + return sema.failWithBadUnionFieldAccess(block, cur_ty, union_obj, field_src, field_name); const field_ty = union_obj.field_types.get(ip)[field_index]; return Air.internedToRef(field_ty); }, @@ -21050,14 +20950,14 @@ fn zirFrame( block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { - const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand)); + const src = block.nodeOffset(@bitCast(extended.operand)); return sema.failWithUseOfAsync(block, src); } fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, operand_src, inst_data.operand); if (ty.isNoReturn(mod)) { return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)}); @@ -21121,7 +21021,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const uncoerced_operand = try sema.resolveInst(inst_data.operand); const operand = try sema.coerce(block, Type.anyerror, uncoerced_operand, operand_src); @@ -21143,7 +21043,7 @@ fn zirAbs( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = try sema.resolveInst(inst_data.operand); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand_ty = sema.typeOf(operand); const scalar_ty = operand_ty.scalarType(mod); @@ -21211,7 +21111,7 @@ fn zirUnaryMath( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = try sema.resolveInst(inst_data.operand); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand_ty = sema.typeOf(operand); const scalar_ty = operand_ty.scalarType(mod); @@ -21233,7 +21133,7 @@ fn zirUnaryMath( fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); @@ -21243,7 +21143,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air try sema.resolveTypeLayout(operand_ty); const enum_ty = switch (operand_ty.zigTypeTag(mod)) { .EnumLiteral => { - const val = try sema.resolveConstDefinedValue(block, .unneeded, operand, undefined); + const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, operand, undefined); const tag_name = ip.indexToKey(val.toIntern()).enum_literal; return sema.addNullTerminatedStrLit(tag_name); }, @@ -21266,13 +21166,12 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const casted_operand = try sema.coerce(block, enum_ty, operand, operand_src); if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| { const field_index = enum_ty.enumTagFieldIndex(val, mod) orelse { - const enum_decl = mod.declPtr(enum_decl_index); const msg = msg: { - const msg = try sema.errMsg(block, src, "no field with value '{}' in enum '{}'", .{ - val.fmtValue(sema.mod, sema), enum_decl.name.fmt(ip), + const msg = try sema.errMsg(src, "no field with value '{}' in enum '{}'", .{ + val.fmtValue(sema.mod, sema), mod.declPtr(enum_decl_index).name.fmt(ip), }); errdefer msg.destroy(sema.gpa); - try mod.errNoteNonLazy(enum_decl.srcLoc(mod), msg, "declared here", .{}); + try sema.errNote(enum_ty.srcLoc(mod), msg, "declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -21303,10 +21202,10 @@ fn zirReify( const ip = &mod.intern_pool; const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); + const src = block.nodeOffset(extra.node); const type_info_ty = try sema.getBuiltinType("Type"); const uncasted_operand = try sema.resolveInst(extra.operand); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const operand_src = block.builtinCallArgSrc(extra.node, 0); const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src); const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .needed_comptime_reason = "operand to @Type must be comptime-known", @@ -21459,11 +21358,10 @@ fn zirReify( } else if (ptr_size == .C) { if (!try sema.validateExternType(elem_ty, .other)) { const msg = msg: { - const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(mod)}); errdefer msg.destroy(gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), elem_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other); try sema.addDeclaredHereNote(msg, elem_ty); break :msg msg; @@ -21679,7 +21577,6 @@ fn zirReify( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x), Value.fromInterned(wip_ty.index), name_strategy, "opaque", @@ -21879,7 +21776,6 @@ fn reifyEnum( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x), Value.fromInterned(wip_ty.index), name_strategy, "enum", @@ -21913,17 +21809,17 @@ fn reifyEnum( if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| { return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) { .name => msg: { - const msg = try sema.errMsg(block, src, "duplicate enum field '{}'", .{field_name.fmt(ip)}); + const msg = try sema.errMsg(src, "duplicate enum field '{}'", .{field_name.fmt(ip)}); errdefer msg.destroy(gpa); _ = conflict.prev_field_idx; // TODO: this note is incorrect - try sema.errNote(block, src, msg, "other field here", .{}); + try sema.errNote(src, msg, "other field here", .{}); break :msg msg; }, .value => msg: { - const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{field_value_val.fmtValue(mod, sema)}); + const msg = try sema.errMsg(src, "enum tag value {} already taken", .{field_value_val.fmtValue(mod, sema)}); errdefer msg.destroy(gpa); _ = conflict.prev_field_idx; // TODO: this note is incorrect - try sema.errNote(block, src, msg, "other enum tag value here", .{}); + try sema.errNote(src, msg, "other enum tag value here", .{}); break :msg msg; }, }); @@ -22026,7 +21922,6 @@ fn reifyUnion( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x), Value.fromInterned(wip_ty.index), name_strategy, "union", @@ -22082,7 +21977,7 @@ fn reifyUnion( } if (tag_ty_fields_len > fields_len) return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "enum fields missing in union", .{}); + const msg = try sema.errMsg(src, "enum fields missing in union", .{}); errdefer msg.destroy(gpa); var it = seen_tags.iterator(.{ .kind = .unset }); while (it.next()) |enum_index| { @@ -22135,7 +22030,7 @@ fn reifyUnion( const field_ty = Type.fromInterned(field_ty_ip); if (field_ty.zigTypeTag(mod) == .Opaque) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); + const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); errdefer msg.destroy(gpa); try sema.addDeclaredHereNote(msg, field_ty); @@ -22144,22 +22039,20 @@ fn reifyUnion( } if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); errdefer msg.destroy(gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), field_ty, .union_field); + try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }); } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); errdefer msg.destroy(gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotPacked(msg, src_decl.toSrcLoc(src, mod), field_ty); + try sema.explainWhyTypeIsNotPacked(msg, src, field_ty); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -22285,7 +22178,6 @@ fn reifyStruct( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x), Value.fromInterned(wip_ty.index), name_strategy, "struct", @@ -22376,7 +22268,7 @@ fn reifyStruct( if (field_ty.zigTypeTag(mod) == .Opaque) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); + const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); errdefer msg.destroy(gpa); try sema.addDeclaredHereNote(msg, field_ty); @@ -22385,7 +22277,7 @@ fn reifyStruct( } if (field_ty.zigTypeTag(mod) == .NoReturn) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{}); + const msg = try sema.errMsg(src, "struct fields cannot be 'noreturn'", .{}); errdefer msg.destroy(gpa); try sema.addDeclaredHereNote(msg, field_ty); @@ -22394,22 +22286,20 @@ fn reifyStruct( } if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); errdefer msg.destroy(gpa); - const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), field_ty, .struct_field); + try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }); } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); errdefer msg.destroy(gpa); - const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotPacked(msg, src_decl.toSrcLoc(src, mod), field_ty); + try sema.explainWhyTypeIsNotPacked(msg, src, field_ty); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -22424,7 +22314,7 @@ fn reifyStruct( sema.resolveTypeLayout(field_ty) catch |err| switch (err) { error.AnalysisFail => { const msg = sema.err orelse return err; - try sema.errNote(block, src, msg, "while checking a field of this struct", .{}); + try sema.errNote(src, msg, "while checking a field of this struct", .{}); return err; }, else => return err, @@ -22455,22 +22345,20 @@ fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.In } fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { - const mod = sema.mod; const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const va_list_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; + const src = block.nodeOffset(extra.node); + const va_list_src = block.builtinCallArgSrc(extra.node, 0); + const ty_src = block.builtinCallArgSrc(extra.node, 1); const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.lhs); const arg_ty = try sema.resolveType(block, ty_src, extra.rhs); if (!try sema.validateExternType(arg_ty, .param_ty)) { const msg = msg: { - const msg = try sema.errMsg(block, ty_src, "cannot get '{}' from variadic argument", .{arg_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(ty_src, "cannot get '{}' from variadic argument", .{arg_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(ty_src, mod), arg_ty, .param_ty); + try sema.explainWhyTypeIsNotExtern(msg, ty_src, arg_ty, .param_ty); try sema.addDeclaredHereNote(msg, arg_ty); break :msg msg; @@ -22484,8 +22372,8 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C fn zirCVaCopy(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const va_list_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const src = block.nodeOffset(extra.node); + const va_list_src = block.builtinCallArgSrc(extra.node, 0); const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand); const va_list_ty = try sema.getBuiltinType("VaList"); @@ -22496,8 +22384,8 @@ fn zirCVaCopy(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const va_list_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const src = block.nodeOffset(extra.node); + const va_list_src = block.builtinCallArgSrc(extra.node, 0); const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand); @@ -22506,7 +22394,7 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C } fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { - const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand)); + const src = block.nodeOffset(@bitCast(extended.operand)); const va_list_ty = try sema.getBuiltinType("VaList"); try sema.requireRuntimeBlock(block, src, null); @@ -22521,7 +22409,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const ip = &mod.intern_pool; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, ty_src, inst_data.operand); const type_name = try ip.getOrPutStringFmt(sema.gpa, "{}", .{ty.fmt(mod)}, .no_embedded_nulls); @@ -22545,7 +22433,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat"); const operand = try sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); @@ -22627,7 +22515,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt"); const operand = try sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); @@ -22671,7 +22559,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand_res = try sema.resolveInst(extra.rhs); const uncoerced_operand_ty = sema.typeOf(operand_res); @@ -22694,9 +22582,9 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! if (ptr_ty.isSlice(mod)) { const msg = msg: { - const msg = try sema.errMsg(block, src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "slice length cannot be inferred from address", .{}); + try sema.errNote(src, msg, "slice length cannot be inferred from address", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -22721,11 +22609,10 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } if (try sema.typeRequiresComptime(ptr_ty)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "pointer to comptime-only type '{}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "pointer to comptime-only type '{}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(src, mod), ptr_ty); + try sema.explainWhyTypeIsComptime(msg, src, ptr_ty); break :msg msg; }); } @@ -22810,8 +22697,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData const mod = sema.mod; const ip = &mod.intern_pool; const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const src = block.nodeOffset(extra.node); + const operand_src = block.builtinCallArgSrc(extra.node, 0); const base_dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_opt, "@errorCast"); const operand = try sema.resolveInst(extra.rhs); const base_operand_ty = sema.typeOf(operand); @@ -22831,12 +22718,12 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData base_dest_ty.errorUnionPayload(mod).toIntern() != base_operand_ty.errorUnionPayload(mod).toIntern()) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "payload types of error unions must match", .{}); + const msg = try sema.errMsg(src, "payload types of error unions must match", .{}); errdefer msg.destroy(sema.gpa); const dest_ty = base_dest_ty.errorUnionPayload(mod); const operand_ty = base_operand_ty.errorUnionPayload(mod); - try sema.errNote(block, src, msg, "destination payload is '{}'", .{dest_ty.fmt(mod)}); - try sema.errNote(block, src, msg, "operand payload is '{}'", .{operand_ty.fmt(mod)}); + try sema.errNote(src, msg, "destination payload is '{}'", .{dest_ty.fmt(mod)}); + try sema.errNote(src, msg, "operand payload is '{}'", .{operand_ty.fmt(mod)}); try addDeclaredHereNote(sema, msg, dest_ty); try addDeclaredHereNote(sema, msg, operand_ty); break :msg msg; @@ -22935,8 +22822,8 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node }; + const src = block.nodeOffset(extra.node); + const operand_src = block.src(.{ .node_offset_ptrcast_operand = extra.node }); const operand = try sema.resolveInst(extra.rhs); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, flags.needResultTypeBuiltinName()); return sema.ptrCastFull( @@ -22953,7 +22840,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrCast"); const operand = try sema.resolveInst(extra.rhs); @@ -23023,7 +22910,7 @@ fn ptrCastFull( if (src_info.flags.size == .C) break :check_size; if (dest_info.flags.size == .C) break :check_size; return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "cannot implicitly convert {s} pointer to {s} pointer", .{ + const msg = try sema.errMsg(src, "cannot implicitly convert {s} pointer to {s} pointer", .{ pointerSizeString(src_info.flags.size), pointerSizeString(dest_info.flags.size), }); @@ -23032,9 +22919,9 @@ fn ptrCastFull( (src_info.flags.size == .Slice or (src_info.flags.size == .One and Type.fromInterned(src_info.child).zigTypeTag(mod) == .Array))) { - try sema.errNote(block, src, msg, "use 'ptr' field to convert slice to many pointer", .{}); + try sema.errNote(src, msg, "use 'ptr' field to convert slice to many pointer", .{}); } else { - try sema.errNote(block, src, msg, "use @ptrCast to change pointer size", .{}); + try sema.errNote(src, msg, "use @ptrCast to change pointer size", .{}); } break :msg msg; }); @@ -23059,13 +22946,13 @@ fn ptrCastFull( ); if (imc_res == .ok) break :check_child; return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "pointer element type '{}' cannot coerce into element type '{}'", .{ + const msg = try sema.errMsg(src, "pointer element type '{}' cannot coerce into element type '{}'", .{ src_child.fmt(mod), dest_child.fmt(mod), }); errdefer msg.destroy(sema.gpa); - try imc_res.report(sema, block, src, msg); - try sema.errNote(block, src, msg, "use @ptrCast to cast pointer element type", .{}); + try imc_res.report(sema, src, msg); + try sema.errNote(src, msg, "use @ptrCast to cast pointer element type", .{}); break :msg msg; }); } @@ -23087,41 +22974,41 @@ fn ptrCastFull( } return sema.failWithOwnedErrorMsg(block, msg: { const msg = if (src_info.sentinel == .none) blk: { - break :blk try sema.errMsg(block, src, "destination pointer requires '{}' sentinel", .{ + break :blk try sema.errMsg(src, "destination pointer requires '{}' sentinel", .{ Value.fromInterned(dest_info.sentinel).fmtValue(mod, sema), }); } else blk: { - break :blk try sema.errMsg(block, src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{ + break :blk try sema.errMsg(src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{ Value.fromInterned(src_info.sentinel).fmtValue(mod, sema), Value.fromInterned(dest_info.sentinel).fmtValue(mod, sema), }); }; errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "use @ptrCast to cast pointer sentinel", .{}); + try sema.errNote(src, msg, "use @ptrCast to cast pointer sentinel", .{}); break :msg msg; }); } if (src_info.packed_offset.host_size != dest_info.packed_offset.host_size) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "pointer host size '{}' cannot coerce into pointer host size '{}'", .{ + const msg = try sema.errMsg(src, "pointer host size '{}' cannot coerce into pointer host size '{}'", .{ src_info.packed_offset.host_size, dest_info.packed_offset.host_size, }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "use @ptrCast to cast pointer host size", .{}); + try sema.errNote(src, msg, "use @ptrCast to cast pointer host size", .{}); break :msg msg; }); } if (src_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "pointer bit offset '{}' cannot coerce into pointer bit offset '{}'", .{ + const msg = try sema.errMsg(src, "pointer bit offset '{}' cannot coerce into pointer bit offset '{}'", .{ src_info.packed_offset.bit_offset, dest_info.packed_offset.bit_offset, }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "use @ptrCast to cast pointer bit offset", .{}); + try sema.errNote(src, msg, "use @ptrCast to cast pointer bit offset", .{}); break :msg msg; }); } @@ -23133,12 +23020,12 @@ fn ptrCastFull( if (dest_allows_zero) break :check_allowzero; return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "'{}' could have null values which are illegal in type '{}'", .{ + const msg = try sema.errMsg(src, "'{}' could have null values which are illegal in type '{}'", .{ operand_ty.fmt(mod), dest_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "use @ptrCast to assert the pointer is not null", .{}); + try sema.errNote(src, msg, "use @ptrCast to assert the pointer is not null", .{}); break :msg msg; }); } @@ -23159,15 +23046,15 @@ fn ptrCastFull( if (!flags.align_cast) { if (dest_align.compare(.gt, src_align)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "{s} increases pointer alignment", .{operation}); + const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ + try sema.errNote(operand_src, msg, "'{}' has alignment '{d}'", .{ operand_ty.fmt(mod), src_align.toByteUnits() orelse 0, }); - try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{ + try sema.errNote(src, msg, "'{}' has alignment '{d}'", .{ dest_ty.fmt(mod), dest_align.toByteUnits() orelse 0, }); - try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); + try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{}); break :msg msg; }); } @@ -23176,15 +23063,15 @@ fn ptrCastFull( if (!flags.addrspace_cast) { if (src_info.flags.address_space != dest_info.flags.address_space) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "{s} changes pointer address space", .{operation}); + const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, operand_src, msg, "'{}' has address space '{s}'", .{ + try sema.errNote(operand_src, msg, "'{}' has address space '{s}'", .{ operand_ty.fmt(mod), @tagName(src_info.flags.address_space), }); - try sema.errNote(block, src, msg, "'{}' has address space '{s}'", .{ + try sema.errNote(src, msg, "'{}' has address space '{s}'", .{ dest_ty.fmt(mod), @tagName(dest_info.flags.address_space), }); - try sema.errNote(block, src, msg, "use @addrSpaceCast to cast pointer address space", .{}); + try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{}); break :msg msg; }); } @@ -23192,9 +23079,9 @@ fn ptrCastFull( // Some address space casts are always disallowed if (!target_util.addrSpaceCastIsValid(mod.getTarget(), src_info.flags.address_space, dest_info.flags.address_space)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "invalid address space cast", .{}); + const msg = try sema.errMsg(src, "invalid address space cast", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, operand_src, msg, "address space '{s}' is not compatible with address space '{s}'", .{ + try sema.errNote(operand_src, msg, "address space '{s}' is not compatible with address space '{s}'", .{ @tagName(src_info.flags.address_space), @tagName(dest_info.flags.address_space), }); @@ -23206,9 +23093,9 @@ fn ptrCastFull( if (!flags.const_cast) { if (src_info.flags.is_const and !dest_info.flags.is_const) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "{s} discards const qualifier", .{operation}); + const msg = try sema.errMsg(src, "{s} discards const qualifier", .{operation}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "use @constCast to discard const qualifier", .{}); + try sema.errNote(src, msg, "use @constCast to discard const qualifier", .{}); break :msg msg; }); } @@ -23217,9 +23104,9 @@ fn ptrCastFull( if (!flags.volatile_cast) { if (src_info.flags.is_volatile and !dest_info.flags.is_volatile) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "{s} discards volatile qualifier", .{operation}); + const msg = try sema.errMsg(src, "{s} discards volatile qualifier", .{operation}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "use @volatileCast to discard volatile qualifier", .{}); + try sema.errNote(src, msg, "use @volatileCast to discard volatile qualifier", .{}); break :msg msg; }); } @@ -23368,8 +23255,8 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node }; + const src = block.nodeOffset(extra.node); + const operand_src = block.src(.{ .node_offset_ptrcast_operand = extra.node }); const operand = try sema.resolveInst(extra.operand); const operand_ty = sema.typeOf(operand); try sema.checkPtrOperand(block, operand_src, operand_ty); @@ -23400,7 +23287,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@truncate"); const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, src); @@ -23438,16 +23325,15 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai if (operand_info.bits < dest_info.bits) { const msg = msg: { const msg = try sema.errMsg( - block, src, "destination type '{}' has more bits than source type '{}'", .{ dest_ty.fmt(mod), operand_ty.fmt(mod) }, ); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "destination type has {d} bits", .{ + try sema.errNote(src, msg, "destination type has {d} bits", .{ dest_info.bits, }); - try sema.errNote(block, operand_src, msg, "operand type has {d} bits", .{ + try sema.errNote(operand_src, msg, "operand type has {d} bits", .{ operand_info.bits, }); break :msg msg; @@ -23490,7 +23376,7 @@ fn zirBitCount( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); _ = try sema.checkIntOrVector(block, operand, operand_src); @@ -23544,7 +23430,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src); @@ -23600,7 +23486,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src); @@ -23658,9 +23544,9 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; - const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); + const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); + const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const ty = try sema.resolveType(block, lhs_src, extra.lhs); @@ -23773,14 +23659,13 @@ fn checkPtrOperand( .Fn => { const msg = msg: { const msg = try sema.errMsg( - block, ty_src, "expected pointer, found '{}'", .{ty.fmt(mod)}, ); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, ty_src, msg, "use '&' to obtain a function pointer", .{}); + try sema.errNote(ty_src, msg, "use '&' to obtain a function pointer", .{}); break :msg msg; }; @@ -23805,14 +23690,13 @@ fn checkPtrType( .Fn => { const msg = msg: { const msg = try sema.errMsg( - block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(mod)}, ); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, ty_src, msg, "use '*const ' to make a function pointer type", .{}); + try sema.errNote(ty_src, msg, "use '*const ' to make a function pointer type", .{}); break :msg msg; }; @@ -24066,26 +23950,26 @@ fn checkVectorizableBinaryOperands( const rhs_len = rhs_ty.arrayLen(mod); if (lhs_len != rhs_len) { const msg = msg: { - const msg = try sema.errMsg(block, src, "vector length mismatch", .{}); + const msg = try sema.errMsg(src, "vector length mismatch", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, lhs_src, msg, "length {d} here", .{lhs_len}); - try sema.errNote(block, rhs_src, msg, "length {d} here", .{rhs_len}); + try sema.errNote(lhs_src, msg, "length {d} here", .{lhs_len}); + try sema.errNote(rhs_src, msg, "length {d} here", .{rhs_len}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); } } else { const msg = msg: { - const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: '{}' and '{}'", .{ + const msg = try sema.errMsg(src, "mixed scalar and vector operands: '{}' and '{}'", .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); if (lhs_is_vector) { - try sema.errNote(block, lhs_src, msg, "vector here", .{}); - try sema.errNote(block, rhs_src, msg, "scalar here", .{}); + try sema.errNote(lhs_src, msg, "vector here", .{}); + try sema.errNote(rhs_src, msg, "scalar here", .{}); } else { - try sema.errNote(block, lhs_src, msg, "scalar here", .{}); - try sema.errNote(block, rhs_src, msg, "vector here", .{}); + try sema.errNote(lhs_src, msg, "scalar here", .{}); + try sema.errNote(rhs_src, msg, "vector here", .{}); } break :msg msg; }; @@ -24093,12 +23977,6 @@ fn checkVectorizableBinaryOperands( } } -fn maybeOptionsSrc(sema: *Sema, block: *Block, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc { - if (base_src == .unneeded) return .unneeded; - const mod = sema.mod; - return mod.optionsSrc(mod.declPtr(block.src_decl), base_src, wanted); -} - fn resolveExportOptions( sema: *Sema, block: *Block, @@ -24112,10 +23990,10 @@ fn resolveExportOptions( const air_ref = try sema.resolveInst(zir_ref); const options = try sema.coerce(block, export_options_ty, air_ref, src); - const name_src = sema.maybeOptionsSrc(block, src, "name"); - const linkage_src = sema.maybeOptionsSrc(block, src, "linkage"); - const section_src = sema.maybeOptionsSrc(block, src, "section"); - const visibility_src = sema.maybeOptionsSrc(block, src, "visibility"); + const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const linkage_src = block.src(.{ .init_field_linkage = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const section_src = block.src(.{ .init_field_section = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const visibility_src = block.src(.{ .init_field_visibility = src.offset.node_offset_builtin_call_arg.builtin_call_node }); const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name", .no_embedded_nulls), name_src); const name = try sema.toConstString(block, name_src, name_operand, .{ @@ -24212,14 +24090,14 @@ fn zirCmpxchg( 1 => .cmpxchg_strong, else => unreachable, }; - const src = LazySrcLoc.nodeOffset(extra.node); + const src = block.nodeOffset(extra.node); // zig fmt: off - const elem_ty_src : LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const ptr_src : LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; - const expected_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = extra.node }; - const new_value_src : LazySrcLoc = .{ .node_offset_builtin_call_arg3 = extra.node }; - const success_order_src: LazySrcLoc = .{ .node_offset_builtin_call_arg4 = extra.node }; - const failure_order_src: LazySrcLoc = .{ .node_offset_builtin_call_arg5 = extra.node }; + const elem_ty_src = block.builtinCallArgSrc(extra.node, 0); + const ptr_src = block.builtinCallArgSrc(extra.node, 1); + const expected_src = block.builtinCallArgSrc(extra.node, 2); + const new_value_src = block.builtinCallArgSrc(extra.node, 3); + const success_order_src = block.builtinCallArgSrc(extra.node, 4); + const failure_order_src = block.builtinCallArgSrc(extra.node, 5); // zig fmt: on const expected_value = try sema.resolveInst(extra.expected_value); const elem_ty = sema.typeOf(expected_value); @@ -24309,7 +24187,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const scalar_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const scalar_src = block.builtinCallArgSrc(inst_data.src_node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@splat"); if (!dest_ty.isVector(mod)) return sema.fail(block, src, "expected vector type, found '{}'", .{dest_ty.fmt(mod)}); @@ -24337,8 +24215,8 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const op_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const op_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 1); const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, "ReduceOp", .{ .needed_comptime_reason = "@reduce operation must be comptime-known", }); @@ -24409,8 +24287,8 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data; - const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const mask_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = inst_data.src_node }; + const elem_ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const mask_src = block.builtinCallArgSrc(inst_data.src_node, 3); const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); try sema.checkVectorElemType(block, elem_ty_src, elem_ty); @@ -24445,9 +24323,9 @@ fn analyzeShuffle( mask_len: u32, ) CompileError!Air.Inst.Ref { const mod = sema.mod; - const a_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = src_node }; - const b_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = src_node }; - const mask_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = src_node }; + const a_src = block.builtinCallArgSrc(src_node, 1); + const b_src = block.builtinCallArgSrc(src_node, 2); + const mask_src = block.builtinCallArgSrc(src_node, 3); var a = a_arg; var b = b_arg; @@ -24511,16 +24389,16 @@ fn analyzeShuffle( } if (unsigned >= operand_info[chosen][0]) { const msg = msg: { - const msg = try sema.errMsg(block, mask_src, "mask index '{d}' has out-of-bounds selection", .{i}); + const msg = try sema.errMsg(mask_src, "mask index '{d}' has out-of-bounds selection", .{i}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, operand_info[chosen][1], msg, "selected index '{d}' out of bounds of '{}'", .{ + try sema.errNote(operand_info[chosen][1], msg, "selected index '{d}' out of bounds of '{}'", .{ unsigned, operand_info[chosen][2].fmt(sema.mod), }); if (chosen == 0) { - try sema.errNote(block, b_src, msg, "selections from the second vector are specified with negative numbers", .{}); + try sema.errNote(b_src, msg, "selections from the second vector are specified with negative numbers", .{}); } break :msg msg; @@ -24598,11 +24476,11 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C const mod = sema.mod; const extra = sema.code.extraData(Zir.Inst.Select, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); - const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const pred_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; - const a_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = extra.node }; - const b_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = extra.node }; + const src = block.nodeOffset(extra.node); + const elem_ty_src = block.builtinCallArgSrc(extra.node, 0); + const pred_src = block.builtinCallArgSrc(extra.node, 1); + const a_src = block.builtinCallArgSrc(extra.node, 2); + const b_src = block.builtinCallArgSrc(extra.node, 3); const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); try sema.checkVectorElemType(block, elem_ty_src, elem_ty); @@ -24689,9 +24567,9 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data; // zig fmt: off - const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const ptr_src : LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; - const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; + const elem_ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 1); + const order_src = block.builtinCallArgSrc(inst_data.src_node, 2); // zig fmt: on const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); const uncasted_ptr = try sema.resolveInst(extra.ptr); @@ -24738,11 +24616,11 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); // zig fmt: off - const elem_ty_src : LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const ptr_src : LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; - const op_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; - const operand_src : LazySrcLoc = .{ .node_offset_builtin_call_arg3 = inst_data.src_node }; - const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg4 = inst_data.src_node }; + const elem_ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 1); + const op_src = block.builtinCallArgSrc(inst_data.src_node, 2); + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 3); + const order_src = block.builtinCallArgSrc(inst_data.src_node, 4); // zig fmt: on const operand = try sema.resolveInst(extra.operand); const elem_ty = sema.typeOf(operand); @@ -24823,10 +24701,10 @@ fn zirAtomicStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const extra = sema.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); // zig fmt: off - const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const ptr_src : LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; - const operand_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; - const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg3 = inst_data.src_node }; + const elem_ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 1); + const operand_src = block.builtinCallArgSrc(inst_data.src_node, 2); + const order_src = block.builtinCallArgSrc(inst_data.src_node, 3); // zig fmt: on const operand = try sema.resolveInst(extra.operand); const elem_ty = sema.typeOf(operand); @@ -24859,9 +24737,9 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const extra = sema.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const mulend1_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; - const mulend2_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; - const addend_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = inst_data.src_node }; + const mulend1_src = block.builtinCallArgSrc(inst_data.src_node, 1); + const mulend2_src = block.builtinCallArgSrc(inst_data.src_node, 2); + const addend_src = block.builtinCallArgSrc(inst_data.src_node, 3); const addend = try sema.resolveInst(extra.addend); const ty = sema.typeOf(addend); @@ -24924,9 +24802,9 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; - const args_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; + const modifier_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const func_src = block.builtinCallArgSrc(inst_data.src_node, 1); + const args_src = block.builtinCallArgSrc(inst_data.src_node, 2); const call_src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data; @@ -25022,8 +24900,8 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); assert(!flags.ptr_cast); const inst_src = block.nodeOffset(extra.src_node); - const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.src_node }; - const field_ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.src_node }; + const field_name_src = block.builtinCallArgSrc(extra.src_node, 0); + const field_ptr_src = block.builtinCallArgSrc(extra.src_node, 1); const parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr"); try sema.checkPtrType(block, inst_src, parent_ptr_ty, true); @@ -25212,9 +25090,9 @@ fn ptrSubtract(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, byte }; if (ptr.byte_offset < byte_subtract) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "pointer computation here causes undefined behavior", .{}); + const msg = try sema.errMsg(src, "pointer computation here causes undefined behavior", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "resulting pointer exceeds bounds of containing value which may trigger overflow", .{}); + try sema.errNote(src, msg, "resulting pointer exceeds bounds of containing value which may trigger overflow", .{}); break :msg msg; }); } @@ -25232,8 +25110,8 @@ fn zirMinMax( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); const lhs = try sema.resolveInst(extra.lhs); const rhs = try sema.resolveInst(extra.rhs); try sema.checkNumericType(block, lhs_src, sema.typeOf(lhs)); @@ -25249,22 +25127,14 @@ fn zirMinMaxMulti( ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); const src_node = extra.data.src_node; - const src = LazySrcLoc.nodeOffset(src_node); + const src = block.nodeOffset(src_node); const operands = sema.code.refSlice(extra.end, extended.small); const air_refs = try sema.arena.alloc(Air.Inst.Ref, operands.len); const operand_srcs = try sema.arena.alloc(LazySrcLoc, operands.len); for (operands, air_refs, operand_srcs, 0..) |zir_ref, *air_ref, *op_src, i| { - op_src.* = switch (i) { - 0 => .{ .node_offset_builtin_call_arg0 = src_node }, - 1 => .{ .node_offset_builtin_call_arg1 = src_node }, - 2 => .{ .node_offset_builtin_call_arg2 = src_node }, - 3 => .{ .node_offset_builtin_call_arg3 = src_node }, - 4 => .{ .node_offset_builtin_call_arg4 = src_node }, - 5 => .{ .node_offset_builtin_call_arg5 = src_node }, - else => src, // TODO: better source location - }; + op_src.* = block.builtinCallArgSrc(src_node, @intCast(i)); air_ref.* = try sema.resolveInst(zir_ref); try sema.checkNumericType(block, op_src.*, sema.typeOf(air_ref.*)); } @@ -25533,8 +25403,8 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const dest_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const src_src = block.builtinCallArgSrc(inst_data.src_node, 1); const dest_ptr = try sema.resolveInst(extra.lhs); const src_ptr = try sema.resolveInst(extra.rhs); const dest_ty = sema.typeOf(dest_ptr); @@ -25550,12 +25420,12 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void if (dest_len == .none and src_len == .none) { const msg = msg: { - const msg = try sema.errMsg(block, src, "unknown @memcpy length", .{}); + const msg = try sema.errMsg(src, "unknown @memcpy length", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{ + try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{ dest_ty.fmt(sema.mod), }); - try sema.errNote(block, src_src, msg, "source type '{}' provides no length", .{ + try sema.errNote(src_src, msg, "source type '{}' provides no length", .{ src_ty.fmt(sema.mod), }); break :msg msg; @@ -25572,12 +25442,12 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void if (try sema.resolveDefinedValue(block, src_src, src_len)) |src_len_val| { if (!(try sema.valuesEqual(dest_len_val, src_len_val, Type.usize))) { const msg = msg: { - const msg = try sema.errMsg(block, src, "non-matching @memcpy lengths", .{}); + const msg = try sema.errMsg(src, "non-matching @memcpy lengths", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, dest_src, msg, "length {} here", .{ + try sema.errNote(dest_src, msg, "length {} here", .{ dest_len_val.fmtValue(sema.mod, sema), }); - try sema.errNote(block, src_src, msg, "length {} here", .{ + try sema.errNote(src_src, msg, "length {} here", .{ src_len_val.fmtValue(sema.mod, sema), }); break :msg msg; @@ -25685,7 +25555,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void } else if (dest_len == .none and len_val == null) { // Change the dest to a slice, since its type must have the length. const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr); - new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false); + new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, LazySrcLoc.unneeded, dest_src, dest_src, dest_src, false); const new_src_ptr_ty = sema.typeOf(new_src_ptr); if (new_src_ptr_ty.isSlice(mod)) { new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty); @@ -25753,8 +25623,8 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); - const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - const value_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const dest_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const value_src = block.builtinCallArgSrc(inst_data.src_node, 1); const dest_ptr = try sema.resolveInst(extra.lhs); const uncoerced_elem = try sema.resolveInst(extra.rhs); const dest_ptr_ty = sema.typeOf(dest_ptr); @@ -25776,9 +25646,9 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void .Many, .C => {}, } return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, src, "unknown @memset length", .{}); + const msg = try sema.errMsg(src, "unknown @memset length", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{ + try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{ dest_ptr_ty.fmt(mod), }); break :msg msg; @@ -25831,7 +25701,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void fn zirBuiltinAsyncCall(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); + const src = block.nodeOffset(extra.node); return sema.failWithUseOfAsync(block, src); } @@ -25858,7 +25728,7 @@ fn zirAwaitNosuspend( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); + const src = block.nodeOffset(extra.node); return sema.failWithUseOfAsync(block, src); } @@ -25870,8 +25740,8 @@ fn zirVarExtended( ) CompileError!Air.Inst.Ref { const mod = sema.mod; const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand); - const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; - const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; + const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 }); + const init_src = block.src(.{ .node_offset_var_decl_init = 0 }); const small: Zir.Inst.ExtendedVar.Small = @bitCast(extended.small); var extra_index: usize = extra.end; @@ -25936,11 +25806,11 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); const target = mod.getTarget(); - const align_src: LazySrcLoc = .{ .node_offset_fn_type_align = inst_data.src_node }; - const addrspace_src: LazySrcLoc = .{ .node_offset_fn_type_addrspace = inst_data.src_node }; - const section_src: LazySrcLoc = .{ .node_offset_fn_type_section = inst_data.src_node }; - const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node }; - const ret_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = inst_data.src_node }; + const align_src = block.src(.{ .node_offset_fn_type_align = inst_data.src_node }); + const addrspace_src = block.src(.{ .node_offset_fn_type_addrspace = inst_data.src_node }); + const section_src = block.src(.{ .node_offset_fn_type_section = inst_data.src_node }); + const cc_src = block.src(.{ .node_offset_fn_type_cc = inst_data.src_node }); + const ret_src = block.src(.{ .node_offset_fn_type_ret_ty = inst_data.src_node }); const has_body = extra.data.body_len != 0; var extra_index: usize = extra.end; @@ -26167,7 +26037,7 @@ fn zirCUndef( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const src = block.builtinCallArgSrc(extra.node, 0); const name = try sema.resolveConstString(block, src, extra.operand, .{ .needed_comptime_reason = "name of macro being undefined must be comptime-known", @@ -26182,7 +26052,7 @@ fn zirCInclude( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; + const src = block.builtinCallArgSrc(extra.node, 0); const name = try sema.resolveConstString(block, src, extra.operand, .{ .needed_comptime_reason = "path being included must be comptime-known", @@ -26198,8 +26068,8 @@ fn zirCDefine( ) CompileError!Air.Inst.Ref { const mod = sema.mod; const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const val_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; + const name_src = block.builtinCallArgSrc(extra.node, 0); + const val_src = block.builtinCallArgSrc(extra.node, 1); const name = try sema.resolveConstString(block, name_src, extra.lhs, .{ .needed_comptime_reason = "name of macro being undefined must be comptime-known", @@ -26222,8 +26092,8 @@ fn zirWasmMemorySize( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const index_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const builtin_src = LazySrcLoc.nodeOffset(extra.node); + const index_src = block.builtinCallArgSrc(extra.node, 0); + const builtin_src = block.nodeOffset(extra.node); const target = sema.mod.getTarget(); if (!target.isWasm()) { return sema.fail(block, builtin_src, "builtin @wasmMemorySize is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)}); @@ -26248,9 +26118,9 @@ fn zirWasmMemoryGrow( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const builtin_src = LazySrcLoc.nodeOffset(extra.node); - const index_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const delta_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; + const builtin_src = block.nodeOffset(extra.node); + const index_src = block.builtinCallArgSrc(extra.node, 0); + const delta_src = block.builtinCallArgSrc(extra.node, 1); const target = sema.mod.getTarget(); if (!target.isWasm()) { return sema.fail(block, builtin_src, "builtin @wasmMemoryGrow is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)}); @@ -26283,9 +26153,9 @@ fn resolvePrefetchOptions( const options_ty = try sema.getBuiltinType("PrefetchOptions"); const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src); - const rw_src = sema.maybeOptionsSrc(block, src, "rw"); - const locality_src = sema.maybeOptionsSrc(block, src, "locality"); - const cache_src = sema.maybeOptionsSrc(block, src, "cache"); + const rw_src = block.src(.{ .init_field_rw = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const locality_src = block.src(.{ .init_field_locality = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const cache_src = block.src(.{ .init_field_cache = src.offset.node_offset_builtin_call_arg.builtin_call_node }); const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "rw", .no_embedded_nulls), rw_src); const rw_val = try sema.resolveConstDefinedValue(block, rw_src, rw, .{ @@ -26315,18 +26185,12 @@ fn zirPrefetch( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const opts_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; + const ptr_src = block.builtinCallArgSrc(extra.node, 0); + const opts_src = block.builtinCallArgSrc(extra.node, 1); const ptr = try sema.resolveInst(extra.lhs); try sema.checkPtrOperand(block, ptr_src, sema.typeOf(ptr)); - const options = sema.resolvePrefetchOptions(block, .unneeded, extra.rhs) catch |err| switch (err) { - error.NeededSourceLocation => { - _ = try sema.resolvePrefetchOptions(block, opts_src, extra.rhs); - unreachable; - }, - else => |e| return e, - }; + const options = try sema.resolvePrefetchOptions(block, opts_src, extra.rhs); if (!block.is_comptime) { _ = try block.addInst(.{ @@ -26361,10 +26225,10 @@ fn resolveExternOptions( const extern_options_ty = try sema.getBuiltinType("ExternOptions"); const options = try sema.coerce(block, extern_options_ty, options_inst, src); - const name_src = sema.maybeOptionsSrc(block, src, "name"); - const library_src = sema.maybeOptionsSrc(block, src, "library"); - const linkage_src = sema.maybeOptionsSrc(block, src, "linkage"); - const thread_local_src = sema.maybeOptionsSrc(block, src, "thread_local"); + const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const library_src = block.src(.{ .init_field_library = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const linkage_src = block.src(.{ .init_field_linkage = src.offset.node_offset_builtin_call_arg.builtin_call_node }); + const thread_local_src = block.src(.{ .init_field_thread_local = src.offset.node_offset_builtin_call_arg.builtin_call_node }); const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name", .no_embedded_nulls), name_src); const name = try sema.toConstString(block, name_src, name_ref, .{ @@ -26422,8 +26286,8 @@ fn zirBuiltinExtern( const mod = sema.mod; const ip = &mod.intern_pool; const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; + const ty_src = block.builtinCallArgSrc(extra.node, 0); + const options_src = block.builtinCallArgSrc(extra.node, 1); var ty = try sema.resolveType(block, ty_src, extra.lhs); if (!ty.isPtrAtRuntime(mod)) { @@ -26431,29 +26295,22 @@ fn zirBuiltinExtern( } if (!try sema.validateExternType(ty, .other)) { const msg = msg: { - const msg = try sema.errMsg(block, ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(mod)}); + const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(ty_src, mod), ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); } - const options = sema.resolveExternOptions(block, .unneeded, extra.rhs) catch |err| switch (err) { - error.NeededSourceLocation => { - _ = try sema.resolveExternOptions(block, options_src, extra.rhs); - unreachable; - }, - else => |e| return e, - }; + const options = try sema.resolveExternOptions(block, options_src, extra.rhs); if (options.linkage == .weak and !ty.ptrAllowsZero(mod)) { ty = try mod.optionalType(ty.toIntern()); } const ptr_info = ty.ptrInfo(mod); - const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node); + const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace); errdefer mod.destroyDecl(new_decl_index); const new_decl = mod.declPtr(new_decl_index); try mod.initNewAnonDecl( @@ -26503,8 +26360,8 @@ fn zirWorkItem( zir_tag: Zir.Inst.Extended, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const dimension_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const builtin_src = LazySrcLoc.nodeOffset(extra.node); + const dimension_src = block.builtinCallArgSrc(extra.node, 0); + const builtin_src = block.nodeOffset(extra.node); const target = sema.mod.getTarget(); switch (target.cpu.arch) { @@ -26545,11 +26402,11 @@ fn zirInComptime( fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void { if (block.is_comptime) { const msg = msg: { - const msg = try sema.errMsg(block, src, "unable to evaluate comptime expression", .{}); + const msg = try sema.errMsg(src, "unable to evaluate comptime expression", .{}); errdefer msg.destroy(sema.gpa); if (runtime_src) |some| { - try sema.errNote(block, some, msg, "operation is runtime due to this operand", .{}); + try sema.errNote(some, msg, "operation is runtime due to this operand", .{}); } if (block.comptime_reason) |some| { try some.explain(sema, msg); @@ -26572,10 +26429,9 @@ fn validateVarType( if (is_extern) { if (!try sema.validateExternType(var_ty, .other)) { const msg = msg: { - const msg = try sema.errMsg(block, src, "extern variable cannot have type '{}'", .{var_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "extern variable cannot have type '{}'", .{var_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), var_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -26594,13 +26450,12 @@ fn validateVarType( if (!try sema.typeRequiresComptime(var_ty)) return; const msg = msg: { - const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty.fmt(mod)}); + const msg = try sema.errMsg(src, "variable of type '{}' must be const or comptime", .{var_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(src, mod), var_ty); + try sema.explainWhyTypeIsComptime(msg, src, var_ty); if (var_ty.zigTypeTag(mod) == .ComptimeInt or var_ty.zigTypeTag(mod) == .ComptimeFloat) { - try sema.errNote(block, src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{}); + try sema.errNote(src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{}); } break :msg msg; @@ -26613,7 +26468,7 @@ const TypeSet = std.AutoHashMapUnmanaged(InternPool.Index, void); fn explainWhyTypeIsComptime( sema: *Sema, msg: *Module.ErrorMsg, - src_loc: Module.SrcLoc, + src_loc: LazySrcLoc, ty: Type, ) CompileError!void { var type_set = TypeSet{}; @@ -26626,7 +26481,7 @@ fn explainWhyTypeIsComptime( fn explainWhyTypeIsComptimeInner( sema: *Sema, msg: *Module.ErrorMsg, - src_loc: Module.SrcLoc, + src_loc: LazySrcLoc, ty: Type, type_set: *TypeSet, ) CompileError!void { @@ -26644,13 +26499,13 @@ fn explainWhyTypeIsComptimeInner( => return, .Fn => { - try mod.errNoteNonLazy(src_loc, msg, "use '*const {}' for a function pointer type", .{ + try sema.errNote(src_loc, msg, "use '*const {}' for a function pointer type", .{ ty.fmt(sema.mod), }); }, .Type => { - try mod.errNoteNonLazy(src_loc, msg, "types are not available at runtime", .{}); + try sema.errNote(src_loc, msg, "types are not available at runtime", .{}); }, .ComptimeFloat, @@ -26662,7 +26517,7 @@ fn explainWhyTypeIsComptimeInner( => return, .Opaque => { - try mod.errNoteNonLazy(src_loc, msg, "opaque type '{}' has undefined size", .{ty.fmt(sema.mod)}); + try sema.errNote(src_loc, msg, "opaque type '{}' has undefined size", .{ty.fmt(sema.mod)}); }, .Array, .Vector => { @@ -26673,14 +26528,14 @@ fn explainWhyTypeIsComptimeInner( if (elem_ty.zigTypeTag(mod) == .Fn) { const fn_info = mod.typeToFunc(elem_ty).?; if (fn_info.is_generic) { - try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{}); + try sema.errNote(src_loc, msg, "function is generic", .{}); } switch (fn_info.cc) { - .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}), + .Inline => try sema.errNote(src_loc, msg, "function has inline calling convention", .{}), else => {}, } if (Type.fromInterned(fn_info.return_type).comptimeOnly(mod)) { - try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{}); + try sema.errNote(src_loc, msg, "function has a comptime-only return type", .{}); } return; } @@ -26700,14 +26555,14 @@ fn explainWhyTypeIsComptimeInner( if (mod.typeToStruct(ty)) |struct_type| { for (0..struct_type.field_types.len) |i| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); - const field_src_loc = mod.fieldSrcLoc(struct_type.decl.unwrap().?, .{ - .index = i, - .range = .type, - }); + const field_src: LazySrcLoc = .{ + .base_node_inst = struct_type.zir_index.unwrap().?, + .offset = .{ .container_field_type = @intCast(i) }, + }; if (try sema.typeRequiresComptime(field_ty)) { - try mod.errNoteNonLazy(field_src_loc, msg, "struct requires comptime because of this field", .{}); - try sema.explainWhyTypeIsComptimeInner(msg, field_src_loc, field_ty, type_set); + try sema.errNote(field_src, msg, "struct requires comptime because of this field", .{}); + try sema.explainWhyTypeIsComptimeInner(msg, field_src, field_ty, type_set); } } } @@ -26720,14 +26575,14 @@ fn explainWhyTypeIsComptimeInner( if (mod.typeToUnion(ty)) |union_obj| { for (0..union_obj.field_types.len) |i| { const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[i]); - const field_src_loc = mod.fieldSrcLoc(union_obj.decl, .{ - .index = i, - .range = .type, - }); + const field_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = .{ .container_field_type = @intCast(i) }, + }; if (try sema.typeRequiresComptime(field_ty)) { - try mod.errNoteNonLazy(field_src_loc, msg, "union requires comptime because of this field", .{}); - try sema.explainWhyTypeIsComptimeInner(msg, field_src_loc, field_ty, type_set); + try sema.errNote(field_src, msg, "union requires comptime because of this field", .{}); + try sema.explainWhyTypeIsComptimeInner(msg, field_src, field_ty, type_set); } } } @@ -26817,7 +26672,7 @@ fn validateExternType( fn explainWhyTypeIsNotExtern( sema: *Sema, msg: *Module.ErrorMsg, - src_loc: Module.SrcLoc, + src_loc: LazySrcLoc, ty: Type, position: ExternPosition, ) CompileError!void { @@ -26842,55 +26697,55 @@ fn explainWhyTypeIsNotExtern( .Pointer => { if (ty.isSlice(mod)) { - try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); + try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); } else { const pointee_ty = ty.childType(mod); if (!ty.isConstPtr(mod) and pointee_ty.zigTypeTag(mod) == .Fn) { - try mod.errNoteNonLazy(src_loc, msg, "pointer to extern function must be 'const'", .{}); + try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{}); } else if (try sema.typeRequiresComptime(ty)) { - try mod.errNoteNonLazy(src_loc, msg, "pointer to comptime-only type '{}'", .{pointee_ty.fmt(sema.mod)}); + try sema.errNote(src_loc, msg, "pointer to comptime-only type '{}'", .{pointee_ty.fmt(sema.mod)}); try sema.explainWhyTypeIsComptime(msg, src_loc, ty); } try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other); } }, - .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), - .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), + .Void => try sema.errNote(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), + .NoReturn => try sema.errNote(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), .Int => if (!std.math.isPowerOfTwo(ty.intInfo(mod).bits)) { - try mod.errNoteNonLazy(src_loc, msg, "only integers with 0 or power of two bits are extern compatible", .{}); + try sema.errNote(src_loc, msg, "only integers with 0 or power of two bits are extern compatible", .{}); } else { - try mod.errNoteNonLazy(src_loc, msg, "only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible", .{}); + try sema.errNote(src_loc, msg, "only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible", .{}); }, .Fn => { if (position != .other) { - try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}); - try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{}); + try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); + try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); return; } switch (ty.fnCallingConvention(mod)) { - .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}), - .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}), - .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}), + .Unspecified => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}), + .Async => try sema.errNote(src_loc, msg, "async function cannot be extern", .{}), + .Inline => try sema.errNote(src_loc, msg, "inline function cannot be extern", .{}), else => return, } }, .Enum => { const tag_ty = ty.intTagType(mod); - try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); + try sema.errNote(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); }, - .Struct => try mod.errNoteNonLazy(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}), - .Union => try mod.errNoteNonLazy(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}), + .Struct => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}), + .Union => try sema.errNote(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}), .Array => { if (position == .ret_ty) { - return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{}); + return sema.errNote(src_loc, msg, "arrays are not allowed as a return type", .{}); } else if (position == .param_ty) { - return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{}); + return sema.errNote(src_loc, msg, "arrays are not allowed as a parameter type", .{}); } try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(mod), .element); }, .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(mod), .element), - .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}), + .Optional => try sema.errNote(src_loc, msg, "only pointer like optionals are extern compatible", .{}), } } @@ -26933,7 +26788,7 @@ fn validatePackedType(sema: *Sema, ty: Type) !bool { fn explainWhyTypeIsNotPacked( sema: *Sema, msg: *Module.ErrorMsg, - src_loc: Module.SrcLoc, + src_loc: LazySrcLoc, ty: Type, ) CompileError!void { const mod = sema.mod; @@ -26959,19 +26814,19 @@ fn explainWhyTypeIsNotPacked( .AnyFrame, .Optional, .Array, - => try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}), + => try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}), .Pointer => if (ty.isSlice(mod)) { - try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); + try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); } else { - try mod.errNoteNonLazy(src_loc, msg, "comptime-only pointer has no guaranteed in-memory representation", .{}); + try sema.errNote(src_loc, msg, "comptime-only pointer has no guaranteed in-memory representation", .{}); try sema.explainWhyTypeIsComptime(msg, src_loc, ty); }, .Fn => { - try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}); - try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{}); + try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); + try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); }, - .Struct => try mod.errNoteNonLazy(src_loc, msg, "only packed structs layout are allowed in packed types", .{}), - .Union => try mod.errNoteNonLazy(src_loc, msg, "only packed unions layout are allowed in packed types", .{}), + .Struct => try sema.errNote(src_loc, msg, "only packed structs layout are allowed in packed types", .{}), + .Union => try sema.errNote(src_loc, msg, "only packed unions layout are allowed in packed types", .{}), } } @@ -27022,11 +26877,11 @@ fn preparePanicId(sema: *Sema, block: *Block, panic_id: Module.PanicId) !InternP const panic_messages_ty = try sema.getBuiltinType("panic_messages"); const msg_decl_index = (sema.namespaceLookup( block, - .unneeded, + LazySrcLoc.unneeded, panic_messages_ty.getNamespaceIndex(mod), try mod.intern_pool.getOrPutString(gpa, @tagName(panic_id), .no_embedded_nulls), ) catch |err| switch (err) { - error.AnalysisFail, error.NeededSourceLocation => @panic("std.builtin.panic_messages is corrupt"), + error.AnalysisFail => @panic("std.builtin.panic_messages is corrupt"), error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, error.OutOfMemory => |e| return e, }).?; @@ -27053,6 +26908,7 @@ fn addSafetyCheck( .instructions = .{}, .inlining = parent_block.inlining, .is_comptime = false, + .src_base_inst = parent_block.src_base_inst, }; defer fail_block.instructions.deinit(gpa); @@ -27161,6 +27017,7 @@ fn panicUnwrapError( .instructions = .{}, .inlining = parent_block.inlining, .is_comptime = false, + .src_base_inst = parent_block.src_base_inst, }; defer fail_block.instructions.deinit(gpa); @@ -27277,6 +27134,7 @@ fn safetyCheckFormatted( .instructions = .{}, .inlining = parent_block.inlining, .is_comptime = false, + .src_base_inst = parent_block.src_base_inst, }; defer fail_block.instructions.deinit(gpa); @@ -27300,13 +27158,11 @@ fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { sema.branch_count += 1; if (sema.branch_count > sema.branch_quota) { const msg = try sema.errMsg( - block, src, "evaluation exceeded {d} backwards branches", .{sema.branch_quota}, ); try sema.errNote( - block, src, msg, "use @setEvalBranchQuota() to raise the branch limit from {d}", @@ -27472,10 +27328,10 @@ fn fieldVal( }, else => { const msg = msg: { - const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(mod)}); + const msg = try sema.errMsg(src, "type '{}' has no members", .{child_type.fmt(mod)}); errdefer msg.destroy(sema.gpa); - if (child_type.isSlice(mod)) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{}); - if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{}); + if (child_type.isSlice(mod)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{}); + if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(src, msg, "array values have 'len' member", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -27633,7 +27489,7 @@ fn fieldPtr( } }, .Type => { - _ = try sema.resolveConstDefinedValue(block, .unneeded, object_ptr, undefined); + _ = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, object_ptr, undefined); const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src); const inner = if (is_pointer_to) try sema.analyzeLoad(block, src, result, object_ptr_src) @@ -27885,7 +27741,7 @@ fn fieldCallBind( }; const msg = msg: { - const msg = try sema.errMsg(block, src, "no field or member function named '{}' in '{}'", .{ + const msg = try sema.errMsg(src, "no field or member function named '{}' in '{}'", .{ field_name.fmt(ip), concrete_ty.fmt(mod), }); @@ -27893,10 +27749,13 @@ fn fieldCallBind( try sema.addDeclaredHereNote(msg, concrete_ty); if (found_decl) |decl_idx| { const decl = mod.declPtr(decl_idx); - try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "'{}' is not a member function", .{field_name.fmt(ip)}); + try sema.errNote(.{ + .base_node_inst = decl.zir_decl_index.unwrap().?, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }, msg, "'{}' is not a member function", .{field_name.fmt(ip)}); } if (concrete_ty.zigTypeTag(mod) == .ErrorUnion) { - try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{}); + try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); } break :msg msg; }; @@ -27954,11 +27813,14 @@ fn namespaceLookup( const decl = mod.declPtr(decl_index); if (!decl.is_pub and decl.getFileScope(mod) != block.getFileScope(mod)) { const msg = msg: { - const msg = try sema.errMsg(block, src, "'{}' is not marked 'pub'", .{ + const msg = try sema.errMsg(src, "'{}' is not marked 'pub'", .{ decl_name.fmt(&mod.intern_pool), }); errdefer msg.destroy(gpa); - try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "declared here", .{}); + try sema.errNote(.{ + .base_node_inst = decl.zir_decl_index.unwrap().?, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }, msg, "declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -28023,7 +27885,7 @@ fn structFieldPtr( const struct_type = mod.typeToStruct(struct_ty).?; const field_index = struct_type.nameIndex(ip, field_name) orelse - return sema.failWithBadStructFieldAccess(block, struct_type, field_name_src, field_name); + return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, field_name_src, struct_ty, initializing); } @@ -28138,7 +28000,7 @@ fn structFieldVal( return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty); const field_index = struct_type.nameIndex(ip, field_name) orelse - return sema.failWithBadStructFieldAccess(block, struct_type, field_name_src, field_name); + return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); if (struct_type.fieldIsComptime(ip, field_index)) { try sema.resolveStructFieldInits(struct_ty); return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]); @@ -28291,7 +28153,7 @@ fn unionFieldPtr( if (initializing and field_ty.zigTypeTag(mod) == .NoReturn) { const msg = msg: { - const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{}); + const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{}); errdefer msg.destroy(sema.gpa); try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{ @@ -28324,7 +28186,7 @@ fn unionFieldPtr( const msg = msg: { const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), mod).?; const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, mod); - const msg = try sema.errMsg(block, src, "access of union field '{}' while field '{}' is active", .{ + const msg = try sema.errMsg(src, "access of union field '{}' while field '{}' is active", .{ field_name.fmt(ip), active_field_name.fmt(ip), }); @@ -28392,7 +28254,7 @@ fn unionFieldVal( const msg = msg: { const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu); - const msg = try sema.errMsg(block, src, "access of union field '{}' while field '{}' is active", .{ + const msg = try sema.errMsg(src, "access of union field '{}' while field '{}' is active", .{ field_name.fmt(ip), active_field_name.fmt(ip), }); errdefer msg.destroy(sema.gpa); @@ -28615,15 +28477,13 @@ fn validateRuntimeElemAccess( if (try sema.typeRequiresComptime(elem_ty)) { const msg = msg: { const msg = try sema.errMsg( - block, elem_index_src, "values of type '{}' must be comptime-known, but index value is runtime-known", .{parent_ty.fmt(mod)}, ); errdefer msg.destroy(sema.gpa); - const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(parent_src, mod), parent_ty); + try sema.explainWhyTypeIsComptime(msg, parent_src, parent_ty); break :msg msg; }; @@ -29011,21 +28871,18 @@ const CoerceOpts = struct { func_inst: Air.Inst.Ref = .none, param_i: u32 = undefined, - fn get(info: @This(), sema: *Sema) !?Module.SrcLoc { + fn get(info: @This(), sema: *Sema) !?LazySrcLoc { if (info.func_inst == .none) return null; - const mod = sema.mod; - const fn_decl = (try sema.funcDeclSrc(info.func_inst)) orelse return null; - const param_src = Module.paramSrc(0, mod, fn_decl, info.param_i); - if (param_src == .node_offset_param) { - return Module.SrcLoc{ - .file_scope = fn_decl.getFileScope(mod), - .parent_decl_node = fn_decl.src_node, - .lazy = LazySrcLoc.nodeOffset(param_src.node_offset_param), - }; - } - return fn_decl.toSrcLoc(param_src, mod); + const fn_decl = try sema.funcDeclSrc(info.func_inst) orelse return null; + return .{ + .base_node_inst = fn_decl.zir_decl_index.unwrap().?, + .offset = .{ .fn_proto_param_type = .{ + .fn_proto_node_offset = 0, + .param_index = info.param_i, + } }, + }; } - } = .{}, + } = .{ .func_inst = .none, .param_i = undefined }, }; fn coerceExtra( @@ -29118,7 +28975,7 @@ fn coerceExtra( // Function body to function pointer. if (inst_ty.zigTypeTag(zcu) == .Fn) { - const fn_val = try sema.resolveConstDefinedValue(block, .unneeded, inst, undefined); + const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); const fn_decl = fn_val.pointerDecl(zcu).?; const inst_as_ptr = try sema.analyzeDeclRef(fn_decl); return sema.coerce(block, dest_ty, inst_as_ptr, inst_src); @@ -29366,9 +29223,9 @@ fn coerceExtra( // pointer to tuple to slice if (!dest_info.flags.is_const) { const err_msg = err_msg: { - const err_msg = try sema.errMsg(block, inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(zcu)}); + const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(zcu)}); errdefer err_msg.destroy(sema.gpa); - try sema.errNote(block, dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{}); + try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{}); break :err_msg err_msg; }; return sema.failWithOwnedErrorMsg(block, err_msg); @@ -29455,7 +29312,7 @@ fn coerceExtra( }, .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag(zcu)) { .ComptimeFloat => { - const val = try sema.resolveConstDefinedValue(block, .unneeded, inst, undefined); + const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); const result_val = try val.floatCast(dest_ty, zcu); return Air.internedToRef(result_val.toIntern()); }, @@ -29514,7 +29371,7 @@ fn coerceExtra( .Enum => switch (inst_ty.zigTypeTag(zcu)) { .EnumLiteral => { // enum literal to enum - const val = try sema.resolveConstDefinedValue(block, .unneeded, inst, undefined); + const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal; const field_index = dest_ty.enumFieldIndex(string, zcu) orelse { return sema.fail(block, inst_src, "no field named '{}' in enum '{}'", .{ @@ -29648,54 +29505,58 @@ fn coerceExtra( if (opts.is_ret and dest_ty.zigTypeTag(zcu) == .NoReturn) { const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "function declared 'noreturn' returns", .{}); + const msg = try sema.errMsg(inst_src, "function declared 'noreturn' returns", .{}); errdefer msg.destroy(sema.gpa); - const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; - const src_decl = zcu.funcOwnerDeclPtr(sema.func_index); - try zcu.errNoteNonLazy(src_decl.toSrcLoc(ret_ty_src, zcu), msg, "'noreturn' declared here", .{}); + const ret_ty_src: LazySrcLoc = .{ + .base_node_inst = zcu.funcOwnerDeclPtr(sema.func_index).zir_decl_index.unwrap().?, + .offset = .{ .node_offset_fn_type_ret_ty = 0 }, + }; + try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); } const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(zcu), inst_ty.fmt(zcu) }); + const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(zcu), inst_ty.fmt(zcu) }); errdefer msg.destroy(sema.gpa); // E!T to T if (inst_ty.zigTypeTag(zcu) == .ErrorUnion and (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src)) == .ok) { - try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{}); - try sema.errNote(block, inst_src, msg, "consider using 'try', 'catch', or 'if'", .{}); + try sema.errNote(inst_src, msg, "cannot convert error union to payload type", .{}); + try sema.errNote(inst_src, msg, "consider using 'try', 'catch', or 'if'", .{}); } // ?T to T if (inst_ty.zigTypeTag(zcu) == .Optional and (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src)) == .ok) { - try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{}); - try sema.errNote(block, inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{}); + try sema.errNote(inst_src, msg, "cannot convert optional to payload type", .{}); + try sema.errNote(inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{}); } - try in_memory_result.report(sema, block, inst_src, msg); + try in_memory_result.report(sema, inst_src, msg); // Add notes about function return type if (opts.is_ret and zcu.test_functions.get(zcu.funcOwnerDeclIndex(sema.func_index)) == null) { - const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; - const src_decl = zcu.funcOwnerDeclPtr(sema.func_index); + const ret_ty_src: LazySrcLoc = .{ + .base_node_inst = zcu.funcOwnerDeclPtr(sema.func_index).zir_decl_index.unwrap().?, + .offset = .{ .node_offset_fn_type_ret_ty = 0 }, + }; if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) { - try zcu.errNoteNonLazy(src_decl.toSrcLoc(ret_ty_src, zcu), msg, "function cannot return an error", .{}); + try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{}); } else { - try zcu.errNoteNonLazy(src_decl.toSrcLoc(ret_ty_src, zcu), msg, "function return type declared here", .{}); + try sema.errNote(ret_ty_src, msg, "function return type declared here", .{}); } } if (try opts.param_src.get(sema)) |param_src| { - try zcu.errNoteNonLazy(param_src, msg, "parameter type declared here", .{}); + try sema.errNote(param_src, msg, "parameter type declared here", .{}); } // TODO maybe add "cannot store an error in type '{}'" note @@ -29830,7 +29691,7 @@ const InMemoryCoercionResult = union(enum) { return res; } - fn report(res: *const InMemoryCoercionResult, sema: *Sema, block: *Block, src: LazySrcLoc, msg: *Module.ErrorMsg) !void { + fn report(res: *const InMemoryCoercionResult, sema: *Sema, src: LazySrcLoc, msg: *Module.ErrorMsg) !void { const mod = sema.mod; var cur = res; while (true) switch (cur.*) { @@ -29841,93 +29702,93 @@ const InMemoryCoercionResult = union(enum) { break; }, .int_not_coercible => |int| { - try sema.errNote(block, src, msg, "{s} {d}-bit int cannot represent all possible {s} {d}-bit values", .{ + try sema.errNote(src, msg, "{s} {d}-bit int cannot represent all possible {s} {d}-bit values", .{ @tagName(int.wanted_signedness), int.wanted_bits, @tagName(int.actual_signedness), int.actual_bits, }); break; }, .error_union_payload => |pair| { - try sema.errNote(block, src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{ + try sema.errNote(src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); cur = pair.child; }, .array_len => |lens| { - try sema.errNote(block, src, msg, "array of length {d} cannot cast into an array of length {d}", .{ + try sema.errNote(src, msg, "array of length {d} cannot cast into an array of length {d}", .{ lens.actual, lens.wanted, }); break; }, .array_sentinel => |sentinel| { if (sentinel.actual.toIntern() != .unreachable_value) { - try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{ + try sema.errNote(src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{ sentinel.actual.fmtValue(mod, sema), sentinel.wanted.fmtValue(mod, sema), }); } else { - try sema.errNote(block, src, msg, "destination array requires '{}' sentinel", .{ + try sema.errNote(src, msg, "destination array requires '{}' sentinel", .{ sentinel.wanted.fmtValue(mod, sema), }); } break; }, .array_elem => |pair| { - try sema.errNote(block, src, msg, "array element type '{}' cannot cast into array element type '{}'", .{ + try sema.errNote(src, msg, "array element type '{}' cannot cast into array element type '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); cur = pair.child; }, .vector_len => |lens| { - try sema.errNote(block, src, msg, "vector of length {d} cannot cast into a vector of length {d}", .{ + try sema.errNote(src, msg, "vector of length {d} cannot cast into a vector of length {d}", .{ lens.actual, lens.wanted, }); break; }, .vector_elem => |pair| { - try sema.errNote(block, src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{ + try sema.errNote(src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); cur = pair.child; }, .optional_shape => |pair| { - try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{ + try sema.errNote(src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{ pair.actual.optionalChild(mod).fmt(mod), pair.wanted.optionalChild(mod).fmt(mod), }); break; }, .optional_child => |pair| { - try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{ + try sema.errNote(src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); cur = pair.child; }, .from_anyerror => { - try sema.errNote(block, src, msg, "global error set cannot cast into a smaller set", .{}); + try sema.errNote(src, msg, "global error set cannot cast into a smaller set", .{}); break; }, .missing_error => |missing_errors| { for (missing_errors) |err| { - try sema.errNote(block, src, msg, "'error.{}' not a member of destination error set", .{err.fmt(&mod.intern_pool)}); + try sema.errNote(src, msg, "'error.{}' not a member of destination error set", .{err.fmt(&mod.intern_pool)}); } break; }, .fn_var_args => |wanted_var_args| { if (wanted_var_args) { - try sema.errNote(block, src, msg, "non-variadic function cannot cast into a variadic function", .{}); + try sema.errNote(src, msg, "non-variadic function cannot cast into a variadic function", .{}); } else { - try sema.errNote(block, src, msg, "variadic function cannot cast into a non-variadic function", .{}); + try sema.errNote(src, msg, "variadic function cannot cast into a non-variadic function", .{}); } break; }, .fn_generic => |wanted_generic| { if (wanted_generic) { - try sema.errNote(block, src, msg, "non-generic function cannot cast into a generic function", .{}); + try sema.errNote(src, msg, "non-generic function cannot cast into a generic function", .{}); } else { - try sema.errNote(block, src, msg, "generic function cannot cast into a non-generic function", .{}); + try sema.errNote(src, msg, "generic function cannot cast into a non-generic function", .{}); } break; }, .fn_param_count => |lens| { - try sema.errNote(block, src, msg, "function with {d} parameters cannot cast into a function with {d} parameters", .{ + try sema.errNote(src, msg, "function with {d} parameters cannot cast into a function with {d} parameters", .{ lens.actual, lens.wanted, }); break; @@ -29944,69 +29805,69 @@ const InMemoryCoercionResult = union(enum) { } } if (!actual_noalias) { - try sema.errNote(block, src, msg, "regular parameter {d} cannot cast into a noalias parameter", .{index}); + try sema.errNote(src, msg, "regular parameter {d} cannot cast into a noalias parameter", .{index}); } else { - try sema.errNote(block, src, msg, "noalias parameter {d} cannot cast into a regular parameter", .{index}); + try sema.errNote(src, msg, "noalias parameter {d} cannot cast into a regular parameter", .{index}); } break; }, .fn_param_comptime => |param| { if (param.wanted) { - try sema.errNote(block, src, msg, "non-comptime parameter {d} cannot cast into a comptime parameter", .{param.index}); + try sema.errNote(src, msg, "non-comptime parameter {d} cannot cast into a comptime parameter", .{param.index}); } else { - try sema.errNote(block, src, msg, "comptime parameter {d} cannot cast into a non-comptime parameter", .{param.index}); + try sema.errNote(src, msg, "comptime parameter {d} cannot cast into a non-comptime parameter", .{param.index}); } break; }, .fn_param => |param| { - try sema.errNote(block, src, msg, "parameter {d} '{}' cannot cast into '{}'", .{ + try sema.errNote(src, msg, "parameter {d} '{}' cannot cast into '{}'", .{ param.index, param.actual.fmt(mod), param.wanted.fmt(mod), }); cur = param.child; }, .fn_cc => |cc| { - try sema.errNote(block, src, msg, "calling convention '{s}' cannot cast into calling convention '{s}'", .{ @tagName(cc.actual), @tagName(cc.wanted) }); + try sema.errNote(src, msg, "calling convention '{s}' cannot cast into calling convention '{s}'", .{ @tagName(cc.actual), @tagName(cc.wanted) }); break; }, .fn_return_type => |pair| { - try sema.errNote(block, src, msg, "return type '{}' cannot cast into return type '{}'", .{ + try sema.errNote(src, msg, "return type '{}' cannot cast into return type '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); cur = pair.child; }, .ptr_child => |pair| { - try sema.errNote(block, src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{ + try sema.errNote(src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); cur = pair.child; }, .ptr_addrspace => |@"addrspace"| { - try sema.errNote(block, src, msg, "address space '{s}' cannot cast into address space '{s}'", .{ @tagName(@"addrspace".actual), @tagName(@"addrspace".wanted) }); + try sema.errNote(src, msg, "address space '{s}' cannot cast into address space '{s}'", .{ @tagName(@"addrspace".actual), @tagName(@"addrspace".wanted) }); break; }, .ptr_sentinel => |sentinel| { if (sentinel.actual.toIntern() != .unreachable_value) { - try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{ + try sema.errNote(src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{ sentinel.actual.fmtValue(mod, sema), sentinel.wanted.fmtValue(mod, sema), }); } else { - try sema.errNote(block, src, msg, "destination pointer requires '{}' sentinel", .{ + try sema.errNote(src, msg, "destination pointer requires '{}' sentinel", .{ sentinel.wanted.fmtValue(mod, sema), }); } break; }, .ptr_size => |size| { - try sema.errNote(block, src, msg, "a {s} pointer cannot cast into a {s} pointer", .{ pointerSizeString(size.actual), pointerSizeString(size.wanted) }); + try sema.errNote(src, msg, "a {s} pointer cannot cast into a {s} pointer", .{ pointerSizeString(size.actual), pointerSizeString(size.wanted) }); break; }, .ptr_qualifiers => |qualifiers| { const ok_const = !qualifiers.actual_const or qualifiers.wanted_const; const ok_volatile = !qualifiers.actual_volatile or qualifiers.wanted_volatile; if (!ok_const) { - try sema.errNote(block, src, msg, "cast discards const qualifier", .{}); + try sema.errNote(src, msg, "cast discards const qualifier", .{}); } else if (!ok_volatile) { - try sema.errNote(block, src, msg, "cast discards volatile qualifier", .{}); + try sema.errNote(src, msg, "cast discards volatile qualifier", .{}); } break; }, @@ -30014,11 +29875,11 @@ const InMemoryCoercionResult = union(enum) { const wanted_allow_zero = pair.wanted.ptrAllowsZero(mod); const actual_allow_zero = pair.actual.ptrAllowsZero(mod); if (actual_allow_zero and !wanted_allow_zero) { - try sema.errNote(block, src, msg, "'{}' could have null values which are illegal in type '{}'", .{ + try sema.errNote(src, msg, "'{}' could have null values which are illegal in type '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); } else { - try sema.errNote(block, src, msg, "mutable '{}' allows illegal null values stored to type '{}'", .{ + try sema.errNote(src, msg, "mutable '{}' allows illegal null values stored to type '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); } @@ -30026,34 +29887,34 @@ const InMemoryCoercionResult = union(enum) { }, .ptr_bit_range => |bit_range| { if (bit_range.actual_host != bit_range.wanted_host) { - try sema.errNote(block, src, msg, "pointer host size '{}' cannot cast into pointer host size '{}'", .{ + try sema.errNote(src, msg, "pointer host size '{}' cannot cast into pointer host size '{}'", .{ bit_range.actual_host, bit_range.wanted_host, }); } if (bit_range.actual_offset != bit_range.wanted_offset) { - try sema.errNote(block, src, msg, "pointer bit offset '{}' cannot cast into pointer bit offset '{}'", .{ + try sema.errNote(src, msg, "pointer bit offset '{}' cannot cast into pointer bit offset '{}'", .{ bit_range.actual_offset, bit_range.wanted_offset, }); } break; }, .ptr_alignment => |pair| { - try sema.errNote(block, src, msg, "pointer alignment '{d}' cannot cast into pointer alignment '{d}'", .{ + try sema.errNote(src, msg, "pointer alignment '{d}' cannot cast into pointer alignment '{d}'", .{ pair.actual.toByteUnits() orelse 0, pair.wanted.toByteUnits() orelse 0, }); break; }, .double_ptr_to_anyopaque => |pair| { - try sema.errNote(block, src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{ + try sema.errNote(src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); break; }, .slice_to_anyopaque => |pair| { - try sema.errNote(block, src, msg, "cannot implicitly cast slice '{}' to anyopaque pointer '{}'", .{ + try sema.errNote(src, msg, "cannot implicitly cast slice '{}' to anyopaque pointer '{}'", .{ pair.actual.fmt(mod), pair.wanted.fmt(mod), }); - try sema.errNote(block, src, msg, "consider using '.ptr'", .{}); + try sema.errNote(src, msg, "consider using '.ptr'", .{}); break; }, }; @@ -30667,7 +30528,7 @@ fn coerceVarArgParam( .{}, ), .Fn => fn_ptr: { - const fn_val = try sema.resolveConstDefinedValue(block, .unneeded, inst, undefined); + const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); const fn_decl = fn_val.pointerDecl(mod).?; break :fn_ptr try sema.analyzeDeclRef(fn_decl); }, @@ -30715,11 +30576,10 @@ fn coerceVarArgParam( const coerced_ty = sema.typeOf(coerced); if (!try sema.validateExternType(coerced_ty, .param_ty)) { const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(inst_src, mod), coerced_ty, .param_ty); + try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty); try sema.addDeclaredHereNote(msg, coerced_ty); break :msg msg; @@ -30879,7 +30739,6 @@ fn checkComptimeKnownStore(sema: *Sema, block: *Block, store_inst_ref: Air.Inst. { try maybe_comptime_alloc.stores.append(sema.arena, .{ .inst = store_inst, - .src_decl = block.src_decl, .src = store_src, }); return; @@ -30913,8 +30772,7 @@ fn checkKnownAllocPtr(sema: *Sema, block: *Block, base_ptr: Air.Inst.Ref, new_pt try maybe_comptime_alloc.stores.append(sema.arena, .{ .inst = new_ptr_inst, - .src_decl = block.src_decl, - .src = .unneeded, + .src = LazySrcLoc.unneeded, }); }, .ptr_elem_ptr => { @@ -30937,10 +30795,9 @@ fn markMaybeComptimeAllocRuntime(sema: *Sema, block: *Block, alloc_inst: Air.Ins const maybe_comptime_alloc = (sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return).value; // Since the alloc has been determined to be runtime, we must check that // all other stores to it are permitted to be runtime values. - const mod = sema.mod; const slice = maybe_comptime_alloc.stores.slice(); - for (slice.items(.inst), slice.items(.src_decl), slice.items(.src)) |other_inst, other_src_decl, other_src| { - if (other_src == .unneeded) { + for (slice.items(.inst), slice.items(.src)) |other_inst, other_src| { + if (other_src.offset == .unneeded) { switch (sema.air_instructions.items(.tag)[@intFromEnum(other_inst)]) { .set_union_tag, .optional_payload_ptr_set, .errunion_payload_ptr_set => continue, else => unreachable, // assertion failure @@ -30950,10 +30807,9 @@ fn markMaybeComptimeAllocRuntime(sema: *Sema, block: *Block, alloc_inst: Air.Ins const other_operand = other_data.rhs; if (!sema.checkRuntimeValue(other_operand)) { return sema.failWithOwnedErrorMsg(block, msg: { - const other_src_resolved = mod.declPtr(other_src_decl).toSrcLoc(other_src, mod); - const msg = try Module.ErrorMsg.create(sema.gpa, other_src_resolved, "runtime value contains reference to comptime var", .{}); + const msg = try sema.errMsg(other_src, "runtime value contains reference to comptime var", .{}); errdefer msg.destroy(sema.gpa); - try mod.errNoteNonLazy(other_src_resolved, msg, "comptime var pointers are not available at runtime", .{}); + try sema.errNote(other_src, msg, "comptime var pointers are not available at runtime", .{}); break :msg msg; }); } @@ -31215,11 +31071,11 @@ fn coerceEnumToUnion( const tag_ty = union_ty.unionTagType(mod) orelse { const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ + const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{ union_ty.fmt(sema.mod), inst_ty.fmt(sema.mod), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, union_ty_src, msg, "cannot coerce enum to untagged union", .{}); + try sema.errNote(union_ty_src, msg, "cannot coerce enum to untagged union", .{}); try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; }; @@ -31239,7 +31095,7 @@ fn coerceEnumToUnion( try sema.resolveTypeFields(field_ty); if (field_ty.zigTypeTag(mod) == .NoReturn) { const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{}); + const msg = try sema.errMsg(inst_src, "cannot initialize 'noreturn' field of union", .{}); errdefer msg.destroy(sema.gpa); const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; @@ -31254,7 +31110,7 @@ fn coerceEnumToUnion( const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse { const msg = msg: { const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; - const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{ + const msg = try sema.errMsg(inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{ inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod), field_ty.fmt(sema.mod), field_name.fmt(ip), }); @@ -31276,7 +31132,7 @@ fn coerceEnumToUnion( if (tag_ty.isNonexhaustiveEnum(mod)) { const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{ + const msg = try sema.errMsg(inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{ union_ty.fmt(sema.mod), }); errdefer msg.destroy(sema.gpa); @@ -31294,7 +31150,6 @@ fn coerceEnumToUnion( for (union_obj.field_types.get(ip), 0..) |field_ty, field_index| { if (Type.fromInterned(field_ty).zigTypeTag(mod) == .NoReturn) { const err_msg = msg orelse try sema.errMsg( - block, inst_src, "runtime coercion from enum '{}' to union '{}' which has a 'noreturn' field", .{ tag_ty.fmt(sema.mod), union_ty.fmt(sema.mod) }, @@ -31318,7 +31173,6 @@ fn coerceEnumToUnion( const msg = msg: { const msg = try sema.errMsg( - block, inst_src, "runtime coercion from enum '{}' to union '{}' which has non-void fields", .{ tag_ty.fmt(sema.mod), union_ty.fmt(sema.mod) }, @@ -31377,12 +31231,10 @@ fn coerceAnonStructToUnion( assert(field_count != 1); const msg = msg: { const msg = if (field_count > 1) try sema.errMsg( - block, inst_src, "cannot initialize multiple union fields at once; unions can only have one active field", .{}, ) else try sema.errMsg( - block, inst_src, "union initializer must initialize one field", .{}, @@ -31459,12 +31311,12 @@ fn coerceArrayLike( const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(mod)); if (dest_len != inst_len) { const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ + const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(mod), inst_ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, dest_ty_src, msg, "destination has length {d}", .{dest_len}); - try sema.errNote(block, inst_src, msg, "source has length {d}", .{inst_len}); + try sema.errNote(dest_ty_src, msg, "destination has length {d}", .{dest_len}); + try sema.errNote(inst_src, msg, "source has length {d}", .{inst_len}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -31546,12 +31398,12 @@ fn coerceTupleToArray( if (dest_len != inst_len) { const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ + const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod), }); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, dest_ty_src, msg, "destination has length {d}", .{dest_len}); - try sema.errNote(block, inst_src, msg, "source has length {d}", .{inst_len}); + try sema.errNote(dest_ty_src, msg, "destination has length {d}", .{dest_len}); + try sema.errNote(inst_src, msg, "source has length {d}", .{inst_len}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -31722,9 +31574,9 @@ fn coerceTupleToStruct( const template = "missing struct field: {}"; const args = .{field_name.fmt(ip)}; if (root_msg) |msg| { - try sema.errNote(block, field_src, msg, template, args); + try sema.errNote(field_src, msg, template, args); } else { - root_msg = try sema.errMsg(block, field_src, template, args); + root_msg = try sema.errMsg(field_src, template, args); } continue; } @@ -31860,18 +31712,18 @@ fn coerceTupleToTuple( const field_name = tuple_ty.structFieldName(i, mod).unwrap() orelse { const template = "missing tuple field: {d}"; if (root_msg) |msg| { - try sema.errNote(block, field_src, msg, template, .{i}); + try sema.errNote(field_src, msg, template, .{i}); } else { - root_msg = try sema.errMsg(block, field_src, template, .{i}); + root_msg = try sema.errMsg(field_src, template, .{i}); } continue; }; const template = "missing struct field: {}"; const args = .{field_name.fmt(ip)}; if (root_msg) |msg| { - try sema.errNote(block, field_src, msg, template, args); + try sema.errNote(field_src, msg, template, args); } else { - root_msg = try sema.errMsg(block, field_src, template, args); + root_msg = try sema.errMsg(field_src, template, args); } continue; } @@ -31926,14 +31778,6 @@ fn addReferencedBy( decl_index: InternPool.DeclIndex, ) !void { if (sema.mod.comp.reference_trace == 0) return; - if (src == .unneeded) { - // We can't use NeededSourceLocation, since sites handling that assume it means a compile - // error. Our long-term strategy here is to gradually transition from NeededSourceLocation - // into having more LazySrcLoc tags. In the meantime, let release compilers just ignore this - // reference (a slightly-incomplete error is better than a crash!), but trigger a panic in - // debug so we can fix this case. - if (std.debug.runtime_safety) unreachable else return; - } try sema.mod.reference_table.put(sema.gpa, decl_index, .{ .referencer = block.src_decl, .src = src, @@ -31945,7 +31789,10 @@ pub fn ensureDeclAnalyzed(sema: *Sema, decl_index: InternPool.DeclIndex) Compile const ip = &mod.intern_pool; const decl = mod.declPtr(decl_index); if (decl.analysis == .in_progress) { - const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(mod), "dependency loop detected", .{}); + const msg = try sema.errMsg(.{ + .base_node_inst = decl.zir_decl_index.unwrap().?, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }, "dependency loop detected", .{}); return sema.failWithOwnedErrorMsg(null, msg); } @@ -32440,10 +32287,9 @@ fn analyzeSlice( if (try sema.compareScalar(start_value, .neq, end_value, Type.comptime_int)) { if (try sema.compareScalar(start_value, .neq, Value.zero_comptime_int, Type.comptime_int)) { const msg = msg: { - const msg = try sema.errMsg(block, start_src, bounds_error_message, .{}); + const msg = try sema.errMsg(start_src, bounds_error_message, .{}); errdefer msg.destroy(sema.gpa); try sema.errNote( - block, start_src, msg, "expected '{}', found '{}'", @@ -32457,10 +32303,9 @@ fn analyzeSlice( return sema.failWithOwnedErrorMsg(block, msg); } else if (try sema.compareScalar(end_value, .neq, Value.one_comptime_int, Type.comptime_int)) { const msg = msg: { - const msg = try sema.errMsg(block, end_src, bounds_error_message, .{}); + const msg = try sema.errMsg(end_src, bounds_error_message, .{}); errdefer msg.destroy(sema.gpa); try sema.errNote( - block, end_src, msg, "expected '{}', found '{}'", @@ -32714,9 +32559,9 @@ fn analyzeSlice( if (!actual_sentinel.eql(expected_sentinel, elem_ty, mod)) { const msg = msg: { - const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{}); + const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{ + try sema.errNote(src, msg, "expected '{}', found '{}'", .{ expected_sentinel.fmtValue(mod, sema), actual_sentinel.fmtValue(mod, sema), }); @@ -33588,6 +33433,31 @@ const PeerResolveStrategy = enum { } }; +const PeerTypeCandidateSrc = union(enum) { + /// Do not print out error notes for candidate sources + none: void, + /// When we want to know the the src of candidate i, look up at + /// index i in this slice + override: []const ?LazySrcLoc, + /// resolvePeerTypes originates from a @TypeOf(...) call + typeof_builtin_call_node_offset: i32, + + pub fn resolve( + self: PeerTypeCandidateSrc, + block: *Block, + candidate_i: usize, + ) ?LazySrcLoc { + return switch (self) { + .none => null, + .override => |candidate_srcs| if (candidate_i >= candidate_srcs.len) + null + else + candidate_srcs[candidate_i], + .typeof_builtin_call_node_offset => |node_offset| block.builtinCallArgSrc(node_offset, @intCast(candidate_i)), + }; + } +}; + const PeerResolveResult = union(enum) { /// The peer type resolution was successful, and resulted in the given type. success: Type, @@ -33612,10 +33482,9 @@ const PeerResolveResult = union(enum) { block: *Block, src: LazySrcLoc, instructions: []const Air.Inst.Ref, - candidate_srcs: Module.PeerTypeCandidateSrc, + candidate_srcs: PeerTypeCandidateSrc, ) !*Module.ErrorMsg { const mod = sema.mod; - const decl_ptr = mod.declPtr(block.src_decl); var opt_msg: ?*Module.ErrorMsg = null; errdefer if (opt_msg) |msg| msg.destroy(sema.gpa); @@ -33643,9 +33512,9 @@ const PeerResolveResult = union(enum) { const fmt = "struct field '{}' has conflicting types"; const args = .{field_error.field_name.fmt(&mod.intern_pool)}; if (opt_msg) |msg| { - try sema.errNote(block, src, msg, fmt, args); + try sema.errNote(src, msg, fmt, args); } else { - opt_msg = try sema.errMsg(block, src, fmt, args); + opt_msg = try sema.errMsg(src, fmt, args); } // Continue on to child error @@ -33667,8 +33536,8 @@ const PeerResolveResult = union(enum) { peer_tys[conflict_idx[1]], }; const conflict_srcs: [2]?LazySrcLoc = .{ - candidate_srcs.resolve(mod, decl_ptr, conflict_idx[0]), - candidate_srcs.resolve(mod, decl_ptr, conflict_idx[1]), + candidate_srcs.resolve(block, conflict_idx[0]), + candidate_srcs.resolve(block, conflict_idx[1]), }; const fmt = "incompatible types: '{}' and '{}'"; @@ -33677,16 +33546,16 @@ const PeerResolveResult = union(enum) { conflict_tys[1].fmt(mod), }; const msg = if (opt_msg) |msg| msg: { - try sema.errNote(block, src, msg, fmt, args); + try sema.errNote(src, msg, fmt, args); break :msg msg; } else msg: { - const msg = try sema.errMsg(block, src, fmt, args); + const msg = try sema.errMsg(src, fmt, args); opt_msg = msg; break :msg msg; }; - if (conflict_srcs[0]) |src_loc| try sema.errNote(block, src_loc, msg, "type '{}' here", .{conflict_tys[0].fmt(mod)}); - if (conflict_srcs[1]) |src_loc| try sema.errNote(block, src_loc, msg, "type '{}' here", .{conflict_tys[1].fmt(mod)}); + if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[0].fmt(mod)}); + if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[1].fmt(mod)}); // No child error break; @@ -33701,7 +33570,7 @@ fn resolvePeerTypes( block: *Block, src: LazySrcLoc, instructions: []const Air.Inst.Ref, - candidate_srcs: Module.PeerTypeCandidateSrc, + candidate_srcs: PeerTypeCandidateSrc, ) !Type { switch (instructions.len) { 0 => return Type.noreturn, @@ -35140,9 +35009,9 @@ pub fn resolveStructAlignment( } fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { - const mod = sema.mod; - const ip = &mod.intern_pool; - const struct_type = mod.typeToStruct(ty) orelse return; + const zcu = sema.mod; + const ip = &zcu.intern_pool; + const struct_type = zcu.typeToStruct(ty) orelse return; if (struct_type.haveLayout(ip)) return; @@ -35150,16 +35019,15 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { try sema.resolveTypeFields(ty); if (struct_type.layout == .@"packed") { - try semaBackingIntType(mod, struct_type); + try semaBackingIntType(zcu, struct_type); return; } if (struct_type.setLayoutWip(ip)) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(struct_type.decl.unwrap().?).srcLoc(mod), + const msg = try sema.errMsg( + ty.srcLoc(zcu), "struct '{}' depends on itself", - .{ty.fmt(mod)}, + .{ty.fmt(zcu)}, ); return sema.failWithOwnedErrorMsg(null, msg); } @@ -35196,9 +35064,8 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { } if (struct_type.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(struct_type.decl.unwrap().?).srcLoc(mod), + const msg = try sema.errMsg( + ty.srcLoc(zcu), "struct layout depends on it having runtime bits", .{}, ); @@ -35206,11 +35073,10 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { } if (struct_type.flagsPtr(ip).assumed_pointer_aligned and - big_align.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8)))) + big_align.compareStrict(.neq, Alignment.fromByteUnits(@divExact(zcu.getTarget().ptrBitWidth(), 8)))) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(struct_type.decl.unwrap().?).srcLoc(mod), + const msg = try sema.errMsg( + ty.srcLoc(zcu), "struct layout depends on being pointer aligned", .{}, ); @@ -35242,7 +35108,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { return a_align.compare(.gt, b_align); } }; - if (struct_type.isTuple(ip) or !mod.backendSupportsFeature(.field_reordering)) { + if (struct_type.isTuple(ip) or !zcu.backendSupportsFeature(.field_reordering)) { // TODO: don't handle tuples differently. This logic exists only because it // uncovers latent bugs if removed. Fix the latent bugs and remove this logic! // Likewise, implement field reordering support in all the backends! @@ -35293,7 +35159,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co var analysis_arena = std.heap.ArenaAllocator.init(gpa); defer analysis_arena.deinit(); - var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); + var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); defer comptime_err_ret_trace.deinit(); var sema: Sema = .{ @@ -35320,6 +35186,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = struct_type.zir_index.unwrap().?, }; defer assert(block.instructions.items.len == 0); @@ -35352,7 +35219,10 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co const backing_int_body_len = zir.extra[extra_index]; extra_index += 1; - const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 }; + const backing_int_src: LazySrcLoc = .{ + .base_node_inst = struct_type.zir_index.unwrap().?, + .offset = .{ .node_offset_container_tag = 0 }, + }; const backing_int_ty = blk: { if (backing_int_body_len == 0) { const backing_int_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); @@ -35368,7 +35238,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); } else { if (fields_bit_sum > std.math.maxInt(u16)) { - return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); + return sema.fail(&block, block.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); } const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum)); struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); @@ -35395,9 +35265,9 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { const mod = sema.mod; if (!ty.isIndexable(mod)) { const msg = msg: { - const msg = try sema.errMsg(block, src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)}); + const msg = try sema.errMsg(src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "operand must be an array, slice, tuple, or vector", .{}); + try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -35418,9 +35288,9 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void } } const msg = msg: { - const msg = try sema.errMsg(block, src, "type '{}' is not an indexable pointer", .{ty.fmt(sema.mod)}); + const msg = try sema.errMsg(src, "type '{}' is not an indexable pointer", .{ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{}); + try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -35471,8 +35341,8 @@ pub fn resolveUnionAlignment( /// This logic must be kept in sync with `Module.getUnionLayout`. fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { - const mod = sema.mod; - const ip = &mod.intern_pool; + const zcu = sema.mod; + const ip = &zcu.intern_pool; try sema.resolveTypeFieldsUnion(ty, ip.loadUnionType(ty.ip_index)); @@ -35482,11 +35352,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { switch (union_type.flagsPtr(ip).status) { .none, .have_field_types => {}, .field_types_wip, .layout_wip => { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(union_type.decl).srcLoc(mod), + const msg = try sema.errMsg( + ty.srcLoc(zcu), "union '{}' depends on itself", - .{ty.fmt(mod)}, + .{ty.fmt(zcu)}, ); return sema.failWithOwnedErrorMsg(null, msg); }, @@ -35505,7 +35374,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { for (0..union_type.field_types.len) |field_index| { const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]); - if (try sema.typeRequiresComptime(field_ty) or field_ty.zigTypeTag(mod) == .NoReturn) continue; // TODO: should this affect alignment? + if (try sema.typeRequiresComptime(field_ty) or field_ty.zigTypeTag(zcu) == .NoReturn) continue; // TODO: should this affect alignment? max_size = @max(max_size, sema.typeAbiSize(field_ty) catch |err| switch (err) { error.AnalysisFail => { @@ -35547,7 +35416,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { } else { // {Payload, Tag} size += max_size; - size = switch (mod.getTarget().ofmt) { + size = switch (zcu.getTarget().ofmt) { .c => max_align, else => tag_align, }.forward(size); @@ -35566,9 +35435,8 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { flags.status = .have_layout; if (union_type.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(union_type.decl).srcLoc(mod), + const msg = try sema.errMsg( + ty.srcLoc(zcu), "union layout depends on it having runtime bits", .{}, ); @@ -35576,11 +35444,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { } if (union_type.flagsPtr(ip).assumed_pointer_aligned and - alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8)))) + alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(zcu.getTarget().ptrBitWidth(), 8)))) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(union_type.decl).srcLoc(mod), + const msg = try sema.errMsg( + ty.srcLoc(zcu), "union layout depends on being pointer aligned", .{}, ); @@ -35804,12 +35671,12 @@ pub fn resolveTypeFieldsStruct( ty: InternPool.Index, struct_type: InternPool.LoadedStructType, ) CompileError!void { - const mod = sema.mod; - const ip = &mod.intern_pool; + const zcu = sema.mod; + const ip = &zcu.intern_pool; // If there is no owner decl it means the struct has no fields. const owner_decl = struct_type.decl.unwrap() orelse return; - switch (mod.declPtr(owner_decl).analysis) { + switch (zcu.declPtr(owner_decl).analysis) { .file_failure, .dependency_failure, .sema_failure, @@ -35823,20 +35690,19 @@ pub fn resolveTypeFieldsStruct( if (struct_type.haveFieldTypes(ip)) return; if (struct_type.setTypesWip(ip)) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(owner_decl).srcLoc(mod), + const msg = try sema.errMsg( + Type.fromInterned(ty).srcLoc(zcu), "struct '{}' depends on itself", - .{Type.fromInterned(ty).fmt(mod)}, + .{Type.fromInterned(ty).fmt(zcu)}, ); return sema.failWithOwnedErrorMsg(null, msg); } defer struct_type.clearTypesWip(ip); - semaStructFields(mod, sema.arena, struct_type) catch |err| switch (err) { + semaStructFields(zcu, sema.arena, struct_type) catch |err| switch (err) { error.AnalysisFail => { - if (mod.declPtr(owner_decl).analysis == .complete) { - mod.declPtr(owner_decl).analysis = .dependency_failure; + if (zcu.declPtr(owner_decl).analysis == .complete) { + zcu.declPtr(owner_decl).analysis = .dependency_failure; } return error.AnalysisFail; }, @@ -35845,9 +35711,9 @@ pub fn resolveTypeFieldsStruct( } pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void { - const mod = sema.mod; - const ip = &mod.intern_pool; - const struct_type = mod.typeToStruct(ty) orelse return; + const zcu = sema.mod; + const ip = &zcu.intern_pool; + const struct_type = zcu.typeToStruct(ty) orelse return; const owner_decl = struct_type.decl.unwrap() orelse return; // Inits can start as resolved @@ -35856,20 +35722,19 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void { try sema.resolveStructLayout(ty); if (struct_type.setInitsWip(ip)) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(owner_decl).srcLoc(mod), + const msg = try sema.errMsg( + ty.srcLoc(zcu), "struct '{}' depends on itself", - .{ty.fmt(mod)}, + .{ty.fmt(zcu)}, ); return sema.failWithOwnedErrorMsg(null, msg); } defer struct_type.clearInitsWip(ip); - semaStructFieldInits(mod, sema.arena, struct_type) catch |err| switch (err) { + semaStructFieldInits(zcu, sema.arena, struct_type) catch |err| switch (err) { error.AnalysisFail => { - if (mod.declPtr(owner_decl).analysis == .complete) { - mod.declPtr(owner_decl).analysis = .dependency_failure; + if (zcu.declPtr(owner_decl).analysis == .complete) { + zcu.declPtr(owner_decl).analysis = .dependency_failure; } return error.AnalysisFail; }, @@ -35879,9 +35744,9 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void { } pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) CompileError!void { - const mod = sema.mod; - const ip = &mod.intern_pool; - const owner_decl = mod.declPtr(union_type.decl); + const zcu = sema.mod; + const ip = &zcu.intern_pool; + const owner_decl = zcu.declPtr(union_type.decl); switch (owner_decl.analysis) { .file_failure, .dependency_failure, @@ -35895,11 +35760,10 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load switch (union_type.flagsPtr(ip).status) { .none => {}, .field_types_wip => { - const msg = try Module.ErrorMsg.create( - sema.gpa, - owner_decl.srcLoc(mod), + const msg = try sema.errMsg( + ty.srcLoc(zcu), "union '{}' depends on itself", - .{ty.fmt(mod)}, + .{ty.fmt(zcu)}, ); return sema.failWithOwnedErrorMsg(null, msg); }, @@ -35913,7 +35777,7 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load union_type.flagsPtr(ip).status = .field_types_wip; errdefer union_type.flagsPtr(ip).status = .none; - semaUnionFields(mod, sema.arena, union_type) catch |err| switch (err) { + semaUnionFields(zcu, sema.arena, union_type) catch |err| switch (err) { error.AnalysisFail => { if (owner_decl.analysis == .complete) { owner_decl.analysis = .dependency_failure; @@ -35963,10 +35827,13 @@ fn resolveInferredErrorSet( } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { if (ies_func_info.is_generic) { const msg = msg: { - const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{}); + const msg = try sema.errMsg(src, "unable to resolve inferred error set of generic function", .{}); errdefer msg.destroy(sema.gpa); - try sema.mod.errNoteNonLazy(ies_func_owner_decl.srcLoc(mod), msg, "generic function declared here", .{}); + try sema.errNote(.{ + .base_node_inst = ies_func_owner_decl.zir_decl_index.unwrap().?, + .offset = LazySrcLoc.Offset.nodeOffset(0), + }, msg, "generic function declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -36147,7 +36014,7 @@ fn semaStructFields( }, }; - var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); + var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); defer comptime_err_ret_trace.deinit(); var sema: Sema = .{ @@ -36174,6 +36041,7 @@ fn semaStructFields( .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = struct_type.zir_index.unwrap().?, }; defer assert(block_scope.instructions.items.len == 0); @@ -36252,35 +36120,19 @@ fn semaStructFields( // so that init values may depend on type layout. for (fields, 0..) |zir_field, field_i| { + const ty_src: LazySrcLoc = .{ + .base_node_inst = struct_type.zir_index.unwrap().?, + .offset = .{ .container_field_type = @intCast(field_i) }, + }; const field_ty: Type = ty: { if (zir_field.type_ref != .none) { - break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) { - error.NeededSourceLocation => { - const ty_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .type, - }).lazy; - _ = try sema.resolveType(&block_scope, ty_src, zir_field.type_ref); - unreachable; - }, - else => |e| return e, - }; + break :ty try sema.resolveType(&block_scope, ty_src, zir_field.type_ref); } assert(zir_field.type_body_len != 0); const body = zir.bodySlice(extra_index, zir_field.type_body_len); extra_index += body.len; const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index); - break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) { - error.NeededSourceLocation => { - const ty_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .type, - }).lazy; - _ = try sema.analyzeAsType(&block_scope, ty_src, ty_ref); - unreachable; - }, - else => |e| return e, - }; + break :ty try sema.analyzeAsType(&block_scope, ty_src, ty_ref); }; if (field_ty.isGenericPoison()) { return error.GenericPoison; @@ -36290,11 +36142,7 @@ fn semaStructFields( if (field_ty.zigTypeTag(mod) == .Opaque) { const msg = msg: { - const ty_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .type, - }).lazy; - const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); + const msg = try sema.errMsg(ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); errdefer msg.destroy(sema.gpa); try sema.addDeclaredHereNote(msg, field_ty); @@ -36304,11 +36152,7 @@ fn semaStructFields( } if (field_ty.zigTypeTag(mod) == .NoReturn) { const msg = msg: { - const ty_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .type, - }).lazy; - const msg = try sema.errMsg(&block_scope, ty_src, "struct fields cannot be 'noreturn'", .{}); + const msg = try sema.errMsg(ty_src, "struct fields cannot be 'noreturn'", .{}); errdefer msg.destroy(sema.gpa); try sema.addDeclaredHereNote(msg, field_ty); @@ -36319,11 +36163,7 @@ fn semaStructFields( switch (struct_type.layout) { .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) { const msg = msg: { - const ty_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .type, - }); - const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); + const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field); @@ -36335,11 +36175,7 @@ fn semaStructFields( }, .@"packed" => if (!try sema.validatePackedType(field_ty)) { const msg = msg: { - const ty_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .type, - }); - const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); + const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty); @@ -36356,17 +36192,11 @@ fn semaStructFields( const body = zir.bodySlice(extra_index, zir_field.align_body_len); extra_index += body.len; const align_ref = try sema.resolveInlineBody(&block_scope, body, zir_index); - const field_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) { - error.NeededSourceLocation => { - const align_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .alignment, - }).lazy; - _ = try sema.analyzeAsAlign(&block_scope, align_src, align_ref); - unreachable; - }, - else => |e| return e, + const align_src: LazySrcLoc = .{ + .base_node_inst = struct_type.zir_index.unwrap().?, + .offset = .{ .container_field_align = @intCast(field_i) }, }; + const field_align = try sema.analyzeAsAlign(&block_scope, align_src, align_ref); struct_type.field_aligns.get(ip)[field_i] = field_align; } @@ -36395,7 +36225,7 @@ fn semaStructFieldInits( const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); - var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); + var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); defer comptime_err_ret_trace.deinit(); var sema: Sema = .{ @@ -36422,6 +36252,7 @@ fn semaStructFieldInits( .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = struct_type.zir_index.unwrap().?, }; defer assert(block_scope.instructions.items.len == 0); @@ -36495,33 +36326,20 @@ fn semaStructFieldInits( try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index}); sema.inst_map.putAssumeCapacity(zir_index, type_ref); - const init = try sema.resolveInlineBody(&block_scope, body, zir_index); - const coerced = sema.coerce(&block_scope, field_ty, init, .unneeded) catch |err| switch (err) { - error.NeededSourceLocation => { - const init_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .value, - }).lazy; - _ = try sema.coerce(&block_scope, field_ty, init, init_src); - unreachable; - }, - else => |e| return e, + const init_src: LazySrcLoc = .{ + .base_node_inst = struct_type.zir_index.unwrap().?, + .offset = .{ .container_field_value = @intCast(field_i) }, }; - const default_val = (try sema.resolveValue(coerced)) orelse { - const init_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .value, - }).lazy; + + const init = try sema.resolveInlineBody(&block_scope, body, zir_index); + const coerced = try sema.coerce(&block_scope, field_ty, init, init_src); + const default_val = try sema.resolveValue(coerced) orelse { return sema.failWithNeededComptime(&block_scope, init_src, .{ .needed_comptime_reason = "struct field default value must be comptime-known", }); }; if (default_val.canMutateComptimeVarState(mod)) { - const init_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .value, - }).lazy; return sema.fail(&block_scope, init_src, "field default value contains reference to comptime-mutable memory", .{}); } struct_type.field_inits.get(ip)[field_i] = default_val.toIntern(); @@ -36543,8 +36361,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len; - const src = LazySrcLoc.nodeOffset(0); - const tag_type_ref: Zir.Inst.Ref = if (small.has_tag_type) blk: { const ty_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); extra_index += 1; @@ -36583,7 +36399,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded const decl = mod.declPtr(decl_index); - var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); + var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); defer comptime_err_ret_trace.deinit(); var sema: Sema = .{ @@ -36610,9 +36426,12 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = union_type.zir_index, }; defer assert(block_scope.instructions.items.len == 0); + const src = block_scope.nodeOffset(0); + if (body.len != 0) { _ = try sema.analyzeInlineBody(&block_scope, body, zir_index); } @@ -36622,7 +36441,10 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}; var explicit_tags_seen: []bool = &.{}; if (tag_type_ref != .none) { - const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x }; + const tag_ty_src: LazySrcLoc = .{ + .base_node_inst = union_type.zir_index, + .offset = .{ .node_offset_container_tag = 0 }, + }; const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref); if (small.auto_enum_tag) { // The provided type is an integer type and we must construct the enum tag type here. @@ -36635,9 +36457,9 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded const field_count_val = try mod.intValue(Type.comptime_int, fields_len - 1); if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) { const msg = msg: { - const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{}); + const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(&block_scope, tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{ + try sema.errNote(tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{ int_tag_ty.fmt(mod), fields_len - 1, }); @@ -36722,19 +36544,26 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded break :blk try sema.resolveInst(tag_ref); } else .none; + const name_src: LazySrcLoc = .{ + .base_node_inst = union_type.zir_index, + .offset = .{ .container_field_name = field_i }, + }; + const value_src: LazySrcLoc = .{ + .base_node_inst = union_type.zir_index, + .offset = .{ .container_field_value = field_i }, + }; + const align_src: LazySrcLoc = .{ + .base_node_inst = union_type.zir_index, + .offset = .{ .container_field_align = field_i }, + }; + const type_src: LazySrcLoc = .{ + .base_node_inst = union_type.zir_index, + .offset = .{ .container_field_type = field_i }, + }; + if (enum_field_vals.capacity() > 0) { const enum_tag_val = if (tag_ref != .none) blk: { - const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) { - error.NeededSourceLocation => { - const val_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .value, - }).lazy; - _ = try sema.semaUnionFieldVal(&block_scope, val_src, int_tag_ty, tag_ref); - unreachable; - }, - else => |e| return e, - }; + const val = try sema.semaUnionFieldVal(&block_scope, value_src, int_tag_ty, tag_ref); last_tag_val = val; break :blk val; @@ -36749,12 +36578,14 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded }; const gop = enum_field_vals.getOrPutAssumeCapacity(enum_tag_val.toIntern()); if (gop.found_existing) { - const field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = field_i }).lazy; - const other_field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = gop.index }).lazy; + const other_value_src: LazySrcLoc = .{ + .base_node_inst = union_type.zir_index, + .offset = .{ .container_field_value = @intCast(gop.index) }, + }; const msg = msg: { - const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{enum_tag_val.fmtValue(mod, &sema)}); + const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{enum_tag_val.fmtValue(mod, &sema)}); errdefer msg.destroy(gpa); - try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{}); + try sema.errNote(other_value_src, msg, "other occurrence here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(&block_scope, msg); @@ -36772,17 +36603,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded else if (field_type_ref == .none) Type.noreturn else - sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) { - error.NeededSourceLocation => { - const ty_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .type, - }).lazy; - _ = try sema.resolveType(&block_scope, ty_src, field_type_ref); - unreachable; - }, - else => |e| return e, - }; + try sema.resolveType(&block_scope, type_src, field_type_ref); if (field_ty.isGenericPoison()) { return error.GenericPoison; @@ -36791,11 +36612,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded if (explicit_tags_seen.len > 0) { const tag_info = ip.loadEnumType(union_type.tagTypePtr(ip).*); const enum_index = tag_info.nameIndex(ip, field_name) orelse { - const ty_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .name, - }).lazy; - return sema.fail(&block_scope, ty_src, "no field named '{}' in enum '{}'", .{ + return sema.fail(&block_scope, name_src, "no field named '{}' in enum '{}'", .{ field_name.fmt(ip), Type.fromInterned(union_type.tagTypePtr(ip).*).fmt(mod), }); }; @@ -36808,17 +36625,15 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded // Enforce the enum fields and the union fields being in the same order. if (enum_index != field_i) { const msg = msg: { - const ty_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .name, - }).lazy; - const enum_field_src = mod.fieldSrcLoc(tag_info.decl, .{ .index = enum_index }).lazy; - const msg = try sema.errMsg(&block_scope, ty_src, "union field '{}' ordered differently than corresponding enum field", .{ + const enum_field_src: LazySrcLoc = .{ + .base_node_inst = tag_info.zir_index.unwrap().?, + .offset = .{ .container_field_name = enum_index }, + }; + const msg = try sema.errMsg(name_src, "union field '{}' ordered differently than corresponding enum field", .{ field_name.fmt(ip), }); errdefer msg.destroy(sema.gpa); - const decl_ptr = mod.declPtr(tag_info.decl); - try mod.errNoteNonLazy(decl_ptr.toSrcLoc(enum_field_src, mod), msg, "enum field here", .{}); + try sema.errNote(enum_field_src, msg, "enum field here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(&block_scope, msg); @@ -36827,11 +36642,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded if (field_ty.zigTypeTag(mod) == .Opaque) { const msg = msg: { - const ty_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .type, - }).lazy; - const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); + const msg = try sema.errMsg(type_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); errdefer msg.destroy(sema.gpa); try sema.addDeclaredHereNote(msg, field_ty); @@ -36844,14 +36655,10 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded !try sema.validateExternType(field_ty, .union_field)) { const msg = msg: { - const ty_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .type, - }); - const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); + const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field); + try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -36859,14 +36666,10 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded return sema.failWithOwnedErrorMsg(&block_scope, msg); } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) { const msg = msg: { - const ty_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .type, - }); - const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); + const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty); + try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -36878,17 +36681,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded if (small.any_aligned_fields) { field_aligns.appendAssumeCapacity(if (align_ref != .none) - sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) { - error.NeededSourceLocation => { - const align_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .alignment, - }).lazy; - _ = try sema.resolveAlign(&block_scope, align_src, align_ref); - unreachable; - }, - else => |e| return e, - } + try sema.resolveAlign(&block_scope, align_src, align_ref) else .none); } else { @@ -36903,7 +36696,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded const tag_info = ip.loadEnumType(union_type.tagTypePtr(ip).*); if (tag_info.names.len > fields_len) { const msg = msg: { - const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{}); + const msg = try sema.errMsg(src, "enum field(s) missing in union", .{}); errdefer msg.destroy(sema.gpa); for (tag_info.names.get(ip), 0..) |field_name, field_index| { @@ -36945,7 +36738,7 @@ fn generateUnionTagTypeNumbered( const ip = &mod.intern_pool; const src_decl = mod.declPtr(block.src_decl); - const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); + const new_decl_index = try mod.allocateNewDecl(block.namespace); errdefer mod.destroyDecl(new_decl_index); const fqn = try union_owner_decl.fullyQualifiedName(mod); const name = try ip.getOrPutStringFmt( @@ -36997,7 +36790,7 @@ fn generateUnionTagTypeSimple( const new_decl_index = new_decl_index: { const fqn = try union_owner_decl.fullyQualifiedName(mod); const src_decl = mod.declPtr(block.src_decl); - const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); + const new_decl_index = try mod.allocateNewDecl(block.namespace); errdefer mod.destroyDecl(new_decl_index); const name = try ip.getOrPutStringFmt( gpa, @@ -37037,8 +36830,7 @@ fn generateUnionTagTypeSimple( } fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { - const gpa = sema.gpa; - const src = LazySrcLoc.nodeOffset(0); + const zcu = sema.mod; var block: Block = .{ .parent = null, @@ -37048,8 +36840,23 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = sema.owner_decl.zir_decl_index.unwrap() orelse owner: { + assert(sema.owner_decl.has_tv); + assert(sema.owner_decl.owns_tv); + switch (sema.owner_decl.typeOf(zcu).zigTypeTag(zcu)) { + .Type => break :owner sema.owner_decl.val.toType().typeDeclInst(zcu).?, + .Fn => { + const owner = zcu.funcInfo(sema.owner_decl.val.toIntern()).generic_owner; + const generic_owner_decl = zcu.declPtr(zcu.funcInfo(owner).owner_decl); + break :owner generic_owner_decl.zir_decl_index.unwrap().?; + }, + else => unreachable, + } + }, }; - defer block.instructions.deinit(gpa); + defer block.instructions.deinit(sema.gpa); + + const src = block.nodeOffset(0); const decl_index = try getBuiltinDecl(sema, &block, name); return sema.analyzeDeclVal(&block, src, decl_index); @@ -37058,7 +36865,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!InternPool.DeclIndex { const gpa = sema.gpa; - const src = LazySrcLoc.nodeOffset(0); + const src = block.nodeOffset(0); const mod = sema.mod; const ip = &mod.intern_pool; @@ -37085,6 +36892,7 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int } fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { + const zcu = sema.mod; const ty_inst = try sema.getBuiltin(name); var block: Block = .{ @@ -37095,9 +36903,23 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { .instructions = .{}, .inlining = null, .is_comptime = true, + .src_base_inst = sema.owner_decl.zir_decl_index.unwrap() orelse owner: { + assert(sema.owner_decl.has_tv); + assert(sema.owner_decl.owns_tv); + switch (sema.owner_decl.typeOf(zcu).zigTypeTag(zcu)) { + .Type => break :owner sema.owner_decl.val.toType().typeDeclInst(zcu).?, + .Fn => { + const owner = zcu.funcInfo(sema.owner_decl.val.toIntern()).generic_owner; + const generic_owner_decl = zcu.declPtr(zcu.funcInfo(owner).owner_decl); + break :owner generic_owner_decl.zir_decl_index.unwrap().?; + }, + else => unreachable, + } + }, }; defer block.instructions.deinit(sema.gpa); - const src = LazySrcLoc.nodeOffset(0); + + const src = block.nodeOffset(0); const result_ty = sema.analyzeAsType(&block, src, ty_inst) catch |err| switch (err) { error.AnalysisFail => std.debug.panic("std.builtin.{s} is corrupt", .{name}), @@ -37113,12 +36935,12 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { /// that the types are already resolved. /// TODO assert the return value matches `ty.onePossibleValue` pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { - const mod = sema.mod; - const ip = &mod.intern_pool; + const zcu = sema.mod; + const ip = &zcu.intern_pool; return switch (ty.toIntern()) { .u0_type, .i0_type, - => try mod.intValue(ty, 0), + => try zcu.intValue(ty, 0), .u1_type, .u8_type, .i8_type, @@ -37181,7 +37003,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { .anyframe_type => unreachable, .null_type => Value.null, .undefined_type => Value.undef, - .optional_noreturn_type => try mod.nullValue(ty), + .optional_noreturn_type => try zcu.nullValue(ty), .generic_poison_type => error.GenericPoison, .empty_struct_type => Value.empty_struct, // values, not types @@ -37295,13 +37117,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { => switch (ip.indexToKey(ty.toIntern())) { inline .array_type, .vector_type => |seq_type, seq_tag| { const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none; - if (seq_type.len + @intFromBool(has_sentinel) == 0) return Value.fromInterned((try mod.intern(.{ .aggregate = .{ + if (seq_type.len + @intFromBool(has_sentinel) == 0) return Value.fromInterned((try zcu.intern(.{ .aggregate = .{ .ty = ty.toIntern(), .storage = .{ .elems = &.{} }, } }))); if (try sema.typeHasOnePossibleValue(Type.fromInterned(seq_type.child))) |opv| { - return Value.fromInterned((try mod.intern(.{ .aggregate = .{ + return Value.fromInterned((try zcu.intern(.{ .aggregate = .{ .ty = ty.toIntern(), .storage = .{ .repeated_elem = opv.toIntern() }, } }))); @@ -37316,7 +37138,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { if (struct_type.field_types.len == 0) { // In this case the struct has no fields at all and // therefore has one possible value. - return Value.fromInterned((try mod.intern(.{ .aggregate = .{ + return Value.fromInterned((try zcu.intern(.{ .aggregate = .{ .ty = ty.toIntern(), .storage = .{ .elems = &.{} }, } }))); @@ -37333,12 +37155,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { continue; } const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); - if (field_ty.eql(ty, mod)) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(struct_type.decl.unwrap().?).srcLoc(mod), + if (field_ty.eql(ty, zcu)) { + const msg = try sema.errMsg( + ty.srcLoc(zcu), "struct '{}' depends on itself", - .{ty.fmt(mod)}, + .{ty.fmt(zcu)}, ); try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{}); return sema.failWithOwnedErrorMsg(null, msg); @@ -37350,7 +37171,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { // In this case the struct has no runtime-known fields and // therefore has one possible value. - return Value.fromInterned((try mod.intern(.{ .aggregate = .{ + return Value.fromInterned((try zcu.intern(.{ .aggregate = .{ .ty = ty.toIntern(), .storage = .{ .elems = field_vals }, } }))); @@ -37363,7 +37184,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { // In this case the struct has all comptime-known fields and // therefore has one possible value. // TODO: write something like getCoercedInts to avoid needing to dupe - return Value.fromInterned((try mod.intern(.{ .aggregate = .{ + return Value.fromInterned((try zcu.intern(.{ .aggregate = .{ .ty = ty.toIntern(), .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values.get(ip)) }, } }))); @@ -37375,23 +37196,22 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypePtr(ip).*))) orelse return null; if (union_obj.field_types.len == 0) { - const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() }); + const only = try zcu.intern(.{ .empty_enum_value = ty.toIntern() }); return Value.fromInterned(only); } const only_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]); - if (only_field_ty.eql(ty, mod)) { - const msg = try Module.ErrorMsg.create( - sema.gpa, - mod.declPtr(union_obj.decl).srcLoc(mod), + if (only_field_ty.eql(ty, zcu)) { + const msg = try sema.errMsg( + ty.srcLoc(zcu), "union '{}' depends on itself", - .{ty.fmt(mod)}, + .{ty.fmt(zcu)}, ); try sema.addFieldErrNote(ty, 0, msg, "while checking this field", .{}); return sema.failWithOwnedErrorMsg(null, msg); } const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse return null; - const only = try mod.intern(.{ .un = .{ + const only = try zcu.intern(.{ .un = .{ .ty = ty.toIntern(), .tag = tag_val.toIntern(), .val = val_val.toIntern(), @@ -37406,7 +37226,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { if (enum_type.tag_ty == .comptime_int_type) return null; if (try sema.typeHasOnePossibleValue(Type.fromInterned(enum_type.tag_ty))) |int_opv| { - const only = try mod.intern(.{ .enum_tag = .{ + const only = try zcu.intern(.{ .enum_tag = .{ .ty = ty.toIntern(), .int = int_opv.toIntern(), } }); @@ -37416,18 +37236,18 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { return null; }, .auto, .explicit => { - if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null; + if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null; return Value.fromInterned(switch (enum_type.names.len) { - 0 => try mod.intern(.{ .empty_enum_value = ty.toIntern() }), - 1 => try mod.intern(.{ .enum_tag = .{ + 0 => try zcu.intern(.{ .empty_enum_value = ty.toIntern() }), + 1 => try zcu.intern(.{ .enum_tag = .{ .ty = ty.toIntern(), .int = if (enum_type.values.len == 0) - (try mod.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern() + (try zcu.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern() else - try mod.intern_pool.getCoercedInts( - mod.gpa, - mod.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int, + try zcu.intern_pool.getCoercedInts( + zcu.gpa, + zcu.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int, enum_type.tag_ty, ), } }), @@ -37765,7 +37585,7 @@ fn unionFieldIndex( try sema.resolveTypeFields(union_ty); const union_obj = mod.typeToUnion(union_ty).?; const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse - return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); + return sema.failWithBadUnionFieldAccess(block, union_ty, union_obj, field_src, field_name); return @intCast(field_index); } @@ -37784,7 +37604,7 @@ fn structFieldIndex( } else { const struct_type = mod.typeToStruct(struct_ty).?; return struct_type.nameIndex(ip, field_name) orelse - return sema.failWithBadStructFieldAccess(block, struct_type, field_src, field_name); + return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_src, field_name); } } @@ -38556,9 +38376,9 @@ fn checkRuntimeValue(sema: *Sema, ptr: Air.Inst.Ref) bool { fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Air.Inst.Ref) CompileError!void { if (sema.checkRuntimeValue(val)) return; return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(block, val_src, "runtime value contains reference to comptime var", .{}); + const msg = try sema.errMsg(val_src, "runtime value contains reference to comptime var", .{}); errdefer msg.destroy(sema.gpa); - try sema.errNote(block, val_src, msg, "comptime var pointers are not available at runtime", .{}); + try sema.errNote(val_src, msg, "comptime var pointers are not available at runtime", .{}); break :msg msg; }); } @@ -38649,6 +38469,14 @@ fn maybeDerefSliceAsArray( return sema.pointerDeref(block, src, casted_ptr, ptr_ty); } +fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void { + if (safety_check and block.wantSafety()) { + try sema.safetyPanic(block, src, .unreach); + } else { + _ = try block.addNoOp(.unreach); + } +} + pub const bitCastVal = @import("Sema/bitcast.zig").bitCast; pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice; diff --git a/src/Sema/comptime_ptr_access.zig b/src/Sema/comptime_ptr_access.zig index 1eddc8d7a6..de0afc4b85 100644 --- a/src/Sema/comptime_ptr_access.zig +++ b/src/Sema/comptime_ptr_access.zig @@ -1025,18 +1025,18 @@ fn checkComptimeVarStore( if (@intFromEnum(runtime_index) < @intFromEnum(block.runtime_index)) { if (block.runtime_cond) |cond_src| { const msg = msg: { - const msg = try sema.errMsg(block, src, "store to comptime variable depends on runtime condition", .{}); + const msg = try sema.errMsg(src, "store to comptime variable depends on runtime condition", .{}); errdefer msg.destroy(sema.gpa); - try sema.mod.errNoteNonLazy(cond_src, msg, "runtime condition here", .{}); + try sema.errNote(cond_src, msg, "runtime condition here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); } if (block.runtime_loop) |loop_src| { const msg = msg: { - const msg = try sema.errMsg(block, src, "cannot store to comptime variable in non-inline loop", .{}); + const msg = try sema.errMsg(src, "cannot store to comptime variable in non-inline loop", .{}); errdefer msg.destroy(sema.gpa); - try sema.mod.errNoteNonLazy(loop_src, msg, "non-inline loop here", .{}); + try sema.errNote(loop_src, msg, "non-inline loop here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); diff --git a/src/Value.zig b/src/Value.zig index 99817d79a9..0eb0364986 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -4014,7 +4014,6 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, zcu: *Zcu) Allocator. return ptr_val.pointerDerivationAdvanced(arena, zcu, null) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.AnalysisFail, - error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak, diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 023c023430..fa3ca6a283 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -16,7 +16,6 @@ const Decl = Module.Decl; const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); const Compilation = @import("../../Compilation.zig"); -const LazySrcLoc = Module.LazySrcLoc; const link = @import("../../link.zig"); const Air = @import("../../Air.zig"); const Liveness = @import("../../Liveness.zig"); @@ -766,7 +765,7 @@ pub fn deinit(func: *CodeGen) void { /// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError { const mod = func.bin_file.base.comp.module.?; - const src_loc = func.decl.srcLoc(mod); + const src_loc = func.decl.navSrcLoc(mod).upgrade(mod); func.err_msg = try Module.ErrorMsg.create(func.gpa, src_loc, fmt, args); return error.CodegenFail; } @@ -3123,7 +3122,7 @@ fn lowerAnonDeclRef( } const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; - const res = try func.bin_file.lowerAnonDecl(decl_val, decl_align, func.decl.srcLoc(mod)); + const res = try func.bin_file.lowerAnonDecl(decl_val, decl_align, func.decl.navSrcLoc(mod).upgrade(mod)); switch (res) { .ok => {}, .fail => |em| { diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index ded960daf1..957100ee34 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -257,7 +257,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { const comp = emit.bin_file.base.comp; const zcu = comp.module.?; const gpa = comp.gpa; - emit.error_msg = try Module.ErrorMsg.create(gpa, zcu.declPtr(emit.decl_index).srcLoc(zcu), format, args); + emit.error_msg = try Module.ErrorMsg.create(gpa, zcu.declPtr(emit.decl_index).navSrcLoc(zcu).upgrade(zcu), format, args); return error.EmitFail; } diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 52290b5ee4..b3a381b278 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -13,7 +13,6 @@ const Type = @import("../type.zig").Type; const C = link.File.C; const Decl = Zcu.Decl; const trace = @import("../tracy.zig").trace; -const LazySrcLoc = Zcu.LazySrcLoc; const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const InternPool = @import("../InternPool.zig"); @@ -638,7 +637,7 @@ pub const DeclGen = struct { const zcu = dg.zcu; const decl_index = dg.pass.decl; const decl = zcu.declPtr(decl_index); - const src_loc = decl.srcLoc(zcu); + const src_loc = decl.navSrcLoc(zcu).upgrade(zcu); dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args); return error.AnalysisFail; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 53ece2c571..aaa33d4beb 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -22,7 +22,6 @@ const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const Value = @import("../Value.zig"); const Type = @import("../type.zig").Type; -const LazySrcLoc = Zcu.LazySrcLoc; const x86_64_abi = @import("../arch/x86_64/abi.zig"); const wasm_c_abi = @import("../arch/wasm/abi.zig"); const aarch64_c_abi = @import("../arch/aarch64/abi.zig"); @@ -2066,7 +2065,7 @@ pub const Object = struct { try o.builder.metadataString(name), file, scope, - owner_decl.src_node + 1, // Line + owner_decl.src_line + 1, // Line try o.lowerDebugType(int_ty), ty.abiSize(mod) * 8, (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, @@ -2236,7 +2235,7 @@ pub const Object = struct { try o.builder.metadataString(name), try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope), try o.namespaceToDebugScope(owner_decl.src_namespace), - owner_decl.src_node + 1, // Line + owner_decl.src_line + 1, // Line .none, // Underlying type 0, // Size 0, // Align @@ -4728,7 +4727,7 @@ pub const DeclGen = struct { const o = dg.object; const gpa = o.gpa; const mod = o.module; - const src_loc = dg.decl.srcLoc(mod); + const src_loc = dg.decl.navSrcLoc(mod).upgrade(mod); dg.err_msg = try Module.ErrorMsg.create(gpa, src_loc, "TODO (LLVM): " ++ format, args); return error.CodegenFail; } diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index aec87b287a..acfdf2b4f8 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -9,7 +9,6 @@ const Module = @import("../Module.zig"); const Decl = Module.Decl; const Type = @import("../type.zig").Type; const Value = @import("../Value.zig"); -const LazySrcLoc = Module.LazySrcLoc; const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const InternPool = @import("../InternPool.zig"); @@ -414,7 +413,7 @@ const DeclGen = struct { pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error { @setCold(true); const mod = self.module; - const src_loc = self.module.declPtr(self.decl_index).srcLoc(mod); + const src_loc = self.module.declPtr(self.decl_index).navSrcLoc(mod).upgrade(mod); assert(self.error_msg == null); self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args); return error.CodegenFail; @@ -6433,7 +6432,7 @@ const DeclGen = struct { // TODO: Translate proper error locations. assert(as.errors.items.len != 0); assert(self.error_msg == null); - const src_loc = self.module.declPtr(self.decl_index).srcLoc(mod); + const src_loc = self.module.declPtr(self.decl_index).navSrcLoc(mod).upgrade(mod); self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{}); const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len); diff --git a/src/crash_report.zig b/src/crash_report.zig index 311647f23f..ed45c32681 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -10,6 +10,7 @@ const native_os = builtin.os.tag; const Module = @import("Module.zig"); const Sema = @import("Sema.zig"); +const InternPool = @import("InternPool.zig"); const Zir = std.zig.Zir; const Decl = Module.Decl; @@ -76,18 +77,19 @@ fn dumpStatusReport() !void { const stderr = io.getStdErr().writer(); const block: *Sema.Block = anal.block; const mod = anal.sema.mod; - const block_src_decl = mod.declPtr(block.src_decl); + + const file, const src_base_node = Module.LazySrcLoc.resolveBaseNode(block.src_base_inst, mod); try stderr.writeAll("Analyzing "); - try writeFullyQualifiedDeclWithFile(mod, block_src_decl, stderr); + try writeFullyQualifiedDeclWithFile(mod, block.src_decl, stderr); try stderr.writeAll("\n"); print_zir.renderInstructionContext( allocator, anal.body, anal.body_index, - mod.namespacePtr(block.namespace).file_scope, - block_src_decl.src_node, + file, + src_base_node, 6, // indent stderr, ) catch |err| switch (err) { @@ -95,21 +97,21 @@ fn dumpStatusReport() !void { else => |e| return e, }; try stderr.writeAll(" For full context, use the command\n zig ast-check -t "); - try writeFilePath(mod.namespacePtr(block.namespace).file_scope, stderr); + try writeFilePath(file, stderr); try stderr.writeAll("\n\n"); var parent = anal.parent; while (parent) |curr| { fba.reset(); try stderr.writeAll(" in "); - const curr_block_src_decl = mod.declPtr(curr.block.src_decl); - try writeFullyQualifiedDeclWithFile(mod, curr_block_src_decl, stderr); + const cur_block_file, const cur_block_src_base_node = Module.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, mod); + try writeFullyQualifiedDeclWithFile(mod, curr.block.src_decl, stderr); try stderr.writeAll("\n > "); print_zir.renderSingleInstruction( allocator, curr.body[curr.body_index], - mod.namespacePtr(curr.block.namespace).file_scope, - curr_block_src_decl.src_node, + cur_block_file, + cur_block_src_base_node, 6, // indent stderr, ) catch |err| switch (err) { @@ -138,7 +140,8 @@ fn writeFilePath(file: *Module.File, writer: anytype) !void { try writer.writeAll(file.sub_file_path); } -fn writeFullyQualifiedDeclWithFile(mod: *Module, decl: *Decl, writer: anytype) !void { +fn writeFullyQualifiedDeclWithFile(mod: *Module, decl_index: InternPool.DeclIndex, writer: anytype) !void { + const decl = mod.declPtr(decl_index); try writeFilePath(decl.getFileScope(mod), writer); try writer.writeAll(": "); try decl.renderFullyQualifiedDebugName(mod, writer); diff --git a/src/link/Coff.zig b/src/link/Coff.zig index d24d69d913..4a58e970c1 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1144,7 +1144,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: const res = try codegen.generateFunction( &self.base, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), func_index, air, liveness, @@ -1181,7 +1181,7 @@ pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclInd const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index }); defer gpa.free(sym_name); const ty = val.typeOf(mod); - const atom_index = switch (try self.lowerConst(sym_name, val, ty.abiAlignment(mod), self.rdata_section_index.?, decl.srcLoc(mod))) { + const atom_index = switch (try self.lowerConst(sym_name, val, ty.abiAlignment(mod), self.rdata_section_index.?, decl.navSrcLoc(mod).upgrade(mod))) { .ok => |atom_index| atom_index, .fail => |em| { decl.analysis = .codegen_failure; @@ -1272,7 +1272,7 @@ pub fn updateDecl( defer code_buffer.deinit(); const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), decl_val, &code_buffer, .none, .{ + const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, .none, .{ .parent_atom_index = atom.getSymbolIndex().?, }); const code = switch (res) { @@ -1313,12 +1313,12 @@ fn updateLazySymbolAtom( const atom = self.getAtomPtr(atom_index); const local_sym_index = atom.getSymbolIndex().?; - const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl| - mod.declPtr(owner_decl).srcLoc(mod) + const src = if (sym.ty.srcLocOrNull(mod)) |src| + src.upgrade(mod) else Module.SrcLoc{ .file_scope = undefined, - .parent_decl_node = undefined, + .base_node = undefined, .lazy = .unneeded, }; const res = try codegen.generateLazySymbol( diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index b27601b420..442f579721 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -1072,7 +1072,7 @@ pub fn updateFunc( const res = if (decl_state) |*ds| try codegen.generateFunction( &elf_file.base, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), func_index, air, liveness, @@ -1082,7 +1082,7 @@ pub fn updateFunc( else try codegen.generateFunction( &elf_file.base, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), func_index, air, liveness, @@ -1156,13 +1156,13 @@ pub fn updateDecl( // TODO implement .debug_info for global variables const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; const res = if (decl_state) |*ds| - try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), decl_val, &code_buffer, .{ + try codegen.generateSymbol(&elf_file.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, .{ .dwarf = ds, }, .{ .parent_atom_index = sym_index, }) else - try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), decl_val, &code_buffer, .none, .{ + try codegen.generateSymbol(&elf_file.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, .none, .{ .parent_atom_index = sym_index, }); @@ -1219,12 +1219,12 @@ fn updateLazySymbol( break :blk try self.strtab.insert(gpa, name); }; - const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl| - mod.declPtr(owner_decl).srcLoc(mod) + const src = if (sym.ty.srcLocOrNull(mod)) |src| + src.upgrade(mod) else Module.SrcLoc{ .file_scope = undefined, - .parent_decl_node = undefined, + .base_node = undefined, .lazy = .unneeded, }; const res = try codegen.generateLazySymbol( @@ -1304,7 +1304,7 @@ pub fn lowerUnnamedConst( val, ty.abiAlignment(mod), elf_file.zig_data_rel_ro_section_index.?, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), )) { .ok => |sym_index| sym_index, .fail => |em| { diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 6168d40d96..cf92503f5a 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -682,7 +682,7 @@ pub fn updateFunc( const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; const res = try codegen.generateFunction( &macho_file.base, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), func_index, air, liveness, @@ -756,7 +756,7 @@ pub fn updateDecl( const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; - const res = try codegen.generateSymbol(&macho_file.base, decl.srcLoc(mod), decl_val, &code_buffer, dio, .{ + const res = try codegen.generateSymbol(&macho_file.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, dio, .{ .parent_atom_index = sym_index, }); @@ -1104,7 +1104,7 @@ pub fn lowerUnnamedConst( val, val.typeOf(mod).abiAlignment(mod), macho_file.zig_const_sect_index.?, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), )) { .ok => |sym_index| sym_index, .fail => |em| { @@ -1294,12 +1294,12 @@ fn updateLazySymbol( break :blk try self.strtab.insert(gpa, name); }; - const src = if (lazy_sym.ty.getOwnerDeclOrNull(mod)) |owner_decl| - mod.declPtr(owner_decl).srcLoc(mod) + const src = if (lazy_sym.ty.srcLocOrNull(mod)) |src| + src.upgrade(mod) else Module.SrcLoc{ .file_scope = undefined, - .parent_decl_node = undefined, + .base_node = undefined, .lazy = .unneeded, }; const res = try codegen.generateLazySymbol( diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index ec5278e62b..ac6ae6752c 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -433,7 +433,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: const res = try codegen.generateFunction( &self.base, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), func_index, air, liveness, @@ -499,7 +499,7 @@ pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIn }; self.syms.items[info.sym_index.?] = sym; - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), val, &code_buffer, .{ + const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod).upgrade(mod), val, &code_buffer, .{ .none = {}, }, .{ .parent_atom_index = new_atom_idx, @@ -538,7 +538,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex) defer code_buffer.deinit(); const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; // TODO we need the symbol index for symbol in the table of locals for the containing atom - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), decl_val, &code_buffer, .{ .none = {} }, .{ + const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = @as(Atom.Index, @intCast(atom_idx)), }); const code = switch (res) { @@ -1020,7 +1020,7 @@ fn addDeclExports( { try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create( gpa, - mod.declPtr(decl_index).srcLoc(mod), + mod.declPtr(decl_index).navSrcLoc(mod).upgrade(mod), "plan9 does not support extra sections", .{}, )); @@ -1212,12 +1212,12 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind self.syms.items[self.getAtomPtr(atom_index).sym_index.?] = symbol; // generate the code - const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl| - mod.declPtr(owner_decl).srcLoc(mod) + const src = if (sym.ty.srcLocOrNull(mod)) |src| + src.upgrade(mod) else Module.SrcLoc{ .file_scope = undefined, - .parent_decl_node = undefined, + .base_node = undefined, .lazy = .unneeded, }; const res = try codegen.generateLazySymbol( diff --git a/src/link/Wasm/ZigObject.zig b/src/link/Wasm/ZigObject.zig index dc49fffaa3..7d9e7e1310 100644 --- a/src/link/Wasm/ZigObject.zig +++ b/src/link/Wasm/ZigObject.zig @@ -269,7 +269,7 @@ pub fn updateDecl( const res = try codegen.generateSymbol( &wasm_file.base, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), val, &code_writer, .none, @@ -308,7 +308,7 @@ pub fn updateFunc( defer code_writer.deinit(); const result = try codegen.generateFunction( &wasm_file.base, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), func_index, air, liveness, @@ -484,7 +484,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, val: Value, d }); defer gpa.free(name); - switch (try zig_object.lowerConst(wasm_file, name, val, decl.srcLoc(mod))) { + switch (try zig_object.lowerConst(wasm_file, name, val, decl.navSrcLoc(mod).upgrade(mod))) { .ok => |atom_index| { try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index); return @intFromEnum(wasm_file.getAtom(atom_index).sym_index); @@ -867,7 +867,7 @@ pub fn updateExports( if (exp.opts.section.toSlice(&mod.intern_pool)) |section| { try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( gpa, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), "Unimplemented: ExportOptions.section '{s}'", .{section}, )); @@ -900,7 +900,7 @@ pub fn updateExports( .link_once => { try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( gpa, - decl.srcLoc(mod), + decl.navSrcLoc(mod).upgrade(mod), "Unimplemented: LinkOnce", .{}, )); diff --git a/src/print_value.zig b/src/print_value.zig index 06ac9f4cd1..e1a63e5b6a 100644 --- a/src/print_value.zig +++ b/src/print_value.zig @@ -32,7 +32,7 @@ pub fn format( return print(ctx.val, writer, ctx.depth, ctx.mod, ctx.opt_sema) catch |err| switch (err) { error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function error.ComptimeBreak, error.ComptimeReturn => unreachable, - error.AnalysisFail, error.NeededSourceLocation => unreachable, // TODO: re-evaluate when we use `opt_sema` more fully + error.AnalysisFail => unreachable, // TODO: re-evaluate when we use `opt_sema` more fully else => |e| return e, }; } diff --git a/src/print_zir.zig b/src/print_zir.zig index 0150a7bacc..e2d2f6e500 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -48,12 +48,11 @@ pub fn renderAsTextToFile( const item = scope_file.zir.extraData(Zir.Inst.Imports.Item, extra_index); extra_index = item.end; - const src: LazySrcLoc = .{ .token_abs = item.data.token }; const import_path = scope_file.zir.nullTerminatedString(item.data.name); try stream.print(" @import(\"{}\") ", .{ std.zig.fmtEscapes(import_path), }); - try writer.writeSrc(stream, src); + try writer.writeSrcTokAbs(stream, item.data.token); try stream.writeAll("\n"); } } @@ -188,7 +187,7 @@ const Writer = struct { } = .{}, fn relativeToNodeIndex(self: *Writer, offset: i32) Ast.Node.Index { - return @as(Ast.Node.Index, @bitCast(offset + @as(i32, @bitCast(self.parent_decl_node)))); + return @bitCast(offset + @as(i32, @bitCast(self.parent_decl_node))); } fn writeInstToStream( @@ -578,10 +577,9 @@ const Writer = struct { .work_group_id, => { const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(inst_data.node); try self.writeInstRef(stream, inst_data.operand); try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, inst_data.node); }, .builtin_extern, @@ -592,12 +590,11 @@ const Writer = struct { .c_va_arg, => { const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(inst_data.node); try self.writeInstRef(stream, inst_data.lhs); try stream.writeAll(", "); try self.writeInstRef(stream, inst_data.rhs); try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, inst_data.node); }, .builtin_async_call => try self.writeBuiltinAsyncCall(stream, extended), @@ -612,9 +609,8 @@ const Writer = struct { } fn writeExtNode(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { - const src = LazySrcLoc.nodeOffset(@as(i32, @bitCast(extended.operand))); try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, @bitCast(extended.operand)); } fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -654,7 +650,7 @@ const Writer = struct { const extra = self.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data; try self.writeInstRef(stream, extra.operand); try stream.print(", {d}) (destructure=", .{extra.expect_len}); - try self.writeSrc(stream, LazySrcLoc.nodeOffset(extra.destructure_node)); + try self.writeSrcNode(stream, extra.destructure_node); try stream.writeAll(") "); try self.writeSrcNode(stream, inst_data.src_node); } @@ -729,7 +725,7 @@ const Writer = struct { try stream.writeAll(")"); } try stream.writeAll(") "); - try self.writeSrc(stream, LazySrcLoc.nodeOffset(extra.data.src_node)); + try self.writeSrcNode(stream, extra.data.src_node); } fn writeInt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -868,7 +864,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.b); try stream.writeAll(") "); - try self.writeSrc(stream, LazySrcLoc.nodeOffset(extra.node)); + try self.writeSrcNode(stream, extra.node); } fn writeMulAdd(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -926,7 +922,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.args); try stream.writeAll(") "); - try self.writeSrc(stream, LazySrcLoc.nodeOffset(extra.node)); + try self.writeSrcNode(stream, extra.node); } fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1056,7 +1052,6 @@ const Writer = struct { fn writeCmpxchg(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); try self.writeInstRef(stream, extra.ptr); try stream.writeAll(", "); @@ -1068,14 +1063,13 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.failure_order); try stream.writeAll(") "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, extra.node); } fn writePtrCastFull(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); if (flags.ptr_cast) try stream.writeAll("ptr_cast, "); if (flags.align_cast) try stream.writeAll("align_cast, "); if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, "); @@ -1085,19 +1079,18 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.rhs); try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, extra.node); } fn writePtrCastNoDest(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); if (flags.const_cast) try stream.writeAll("const_cast, "); if (flags.volatile_cast) try stream.writeAll("volatile_cast, "); try self.writeInstRef(stream, extra.operand); try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, extra.node); } fn writeAtomicLoad(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1183,7 +1176,6 @@ const Writer = struct { fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); - const src = LazySrcLoc.nodeOffset(extra.data.src_node); const operands = self.code.refSlice(extra.end, extended.small); for (operands, 0..) |operand, i| { @@ -1191,7 +1183,7 @@ const Writer = struct { try self.writeInstRef(stream, operand); } try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, extra.data.src_node); } fn writeInstNode( @@ -1212,7 +1204,6 @@ const Writer = struct { tmpl_is_expr: bool, ) !void { const extra = self.code.extraData(Zir.Inst.Asm, extended.operand); - const src = LazySrcLoc.nodeOffset(extra.data.src_node); const outputs_len = @as(u5, @truncate(extended.small)); const inputs_len = @as(u5, @truncate(extended.small >> 5)); const clobbers_len = @as(u5, @truncate(extended.small >> 10)); @@ -1283,18 +1274,17 @@ const Writer = struct { } } try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, extra.data.src_node); } fn writeOverflowArithmetic(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; - const src = LazySrcLoc.nodeOffset(extra.node); try self.writeInstRef(stream, extra.lhs); try stream.writeAll(", "); try self.writeInstRef(stream, extra.rhs); try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, extra.node); } fn writeCall( @@ -2287,9 +2277,8 @@ const Writer = struct { inst: Zir.Inst.Index, ) (@TypeOf(stream).Error || error{OutOfMemory})!void { const src_node = self.code.instructions.items(.data)[@intFromEnum(inst)].node; - const src = LazySrcLoc.nodeOffset(src_node); try stream.writeAll(") "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, src_node); } fn writeStrTok( @@ -2507,7 +2496,6 @@ const Writer = struct { fn writeAllocExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand); const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small)); - const src = LazySrcLoc.nodeOffset(extra.data.src_node); var extra_index: usize = extra.end; const type_inst: Zir.Inst.Ref = if (!small.has_type) .none else blk: { @@ -2525,7 +2513,7 @@ const Writer = struct { try self.writeOptionalInstRef(stream, ",ty=", type_inst); try self.writeOptionalInstRef(stream, ",align=", align_inst); try stream.writeAll(")) "); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, extra.data.src_node); } fn writeTypeofPeer(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { @@ -2780,9 +2768,8 @@ const Writer = struct { } fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { - const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand)); try stream.print("{d})) ", .{extended.small}); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, @bitCast(extended.operand)); } fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { @@ -2858,30 +2845,44 @@ const Writer = struct { try stream.writeAll(name); } - fn writeSrc(self: *Writer, stream: anytype, src: LazySrcLoc) !void { - if (self.file.tree_loaded) { - const tree = self.file.tree; - const src_loc: Module.SrcLoc = .{ - .file_scope = self.file, - .parent_decl_node = self.parent_decl_node, - .lazy = src, - }; - const src_span = src_loc.span(self.gpa) catch unreachable; - const start = self.line_col_cursor.find(tree.source, src_span.start); - const end = self.line_col_cursor.find(tree.source, src_span.end); - try stream.print("{s}:{d}:{d} to :{d}:{d}", .{ - @tagName(src), start.line + 1, start.column + 1, - end.line + 1, end.column + 1, - }); - } - } - fn writeSrcNode(self: *Writer, stream: anytype, src_node: i32) !void { - return self.writeSrc(stream, LazySrcLoc.nodeOffset(src_node)); + if (!self.file.tree_loaded) return; + const tree = self.file.tree; + const abs_node = self.relativeToNodeIndex(src_node); + const src_span = tree.nodeToSpan(abs_node); + const start = self.line_col_cursor.find(tree.source, src_span.start); + const end = self.line_col_cursor.find(tree.source, src_span.end); + try stream.print("node_offset:{d}:{d} to :{d}:{d}", .{ + start.line + 1, start.column + 1, + end.line + 1, end.column + 1, + }); } fn writeSrcTok(self: *Writer, stream: anytype, src_tok: u32) !void { - return self.writeSrc(stream, .{ .token_offset = src_tok }); + if (!self.file.tree_loaded) return; + const tree = self.file.tree; + const abs_tok = tree.firstToken(self.parent_decl_node) + src_tok; + const span_start = tree.tokens.items(.start)[abs_tok]; + const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len)); + const start = self.line_col_cursor.find(tree.source, span_start); + const end = self.line_col_cursor.find(tree.source, span_end); + try stream.print("token_offset:{d}:{d} to :{d}:{d}", .{ + start.line + 1, start.column + 1, + end.line + 1, end.column + 1, + }); + } + + fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: u32) !void { + if (!self.file.tree_loaded) return; + const tree = self.file.tree; + const span_start = tree.tokens.items(.start)[src_tok]; + const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len)); + const start = self.line_col_cursor.find(tree.source, span_start); + const end = self.line_col_cursor.find(tree.source, span_end); + try stream.print("token_abs:{d}:{d} to :{d}:{d}", .{ + start.line + 1, start.column + 1, + end.line + 1, end.column + 1, + }); } fn writeBracedDecl(self: *Writer, stream: anytype, body: []const Zir.Inst.Index) !void { diff --git a/src/type.zig b/src/type.zig index 5dad904ca0..546234db37 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3317,15 +3317,6 @@ pub const Type = struct { } } - pub fn declSrcLoc(ty: Type, mod: *Module) Module.SrcLoc { - return declSrcLocOrNull(ty, mod).?; - } - - pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc { - const decl = ty.getOwnerDeclOrNull(mod) orelse return null; - return mod.declPtr(decl).srcLoc(mod); - } - pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex { return ty.getOwnerDeclOrNull(mod) orelse unreachable; } @@ -3341,6 +3332,37 @@ pub const Type = struct { }; } + pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Module.LazySrcLoc { + const ip = &zcu.intern_pool; + return .{ + .base_node_inst = switch (ip.indexToKey(ty.toIntern())) { + .struct_type => |info| switch (info) { + .declared => ip.loadStructType(ty.toIntern()).zir_index.unwrap() orelse return null, + else => return null, + }, + .union_type => |info| switch (info) { + .declared => ip.loadUnionType(ty.toIntern()).zir_index, + else => return null, + }, + .opaque_type => |info| switch (info) { + .declared => ip.loadOpaqueType(ty.toIntern()).zir_index, + else => return null, + }, + .enum_type => |info| switch (info) { + .declared => ip.loadEnumType(ty.toIntern()).zir_index.unwrap().?, + .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, // must be declared since we can't generate tags when reifying + else => return null, + }, + else => return null, + }, + .offset = Module.LazySrcLoc.Offset.nodeOffset(0), + }; + } + + pub fn srcLoc(ty: Type, zcu: *Zcu) Module.LazySrcLoc { + return ty.srcLocOrNull(zcu).?; + } + pub fn isGenericPoison(ty: Type) bool { return ty.toIntern() == .generic_poison_type; } diff --git a/test/cases/compile_errors/comptime_arg_to_generic_fn_callee_error.zig b/test/cases/compile_errors/comptime_arg_to_generic_fn_callee_error.zig index efc3f556a9..8d8516eecc 100644 --- a/test/cases/compile_errors/comptime_arg_to_generic_fn_callee_error.zig +++ b/test/cases/compile_errors/comptime_arg_to_generic_fn_callee_error.zig @@ -18,4 +18,3 @@ pub export fn entry() void { // target=native // // :7:28: error: no field named 'c' in enum 'meta.FieldEnum(tmp.MyStruct)' -// :?:?: note: enum declared here diff --git a/test/cases/compile_errors/enum_value_already_taken.zig b/test/cases/compile_errors/enum_value_already_taken.zig index e3a13785e1..efb9e209cf 100644 --- a/test/cases/compile_errors/enum_value_already_taken.zig +++ b/test/cases/compile_errors/enum_value_already_taken.zig @@ -15,4 +15,4 @@ export fn entry() void { // target=native // // :6:9: error: enum tag value 60 already taken -// :4:5: note: other occurrence here +// :4:9: note: other occurrence here diff --git a/test/cases/compile_errors/export_function_with_comptime_parameter.zig b/test/cases/compile_errors/export_function_with_comptime_parameter.zig index 948053534d..8d5dbef1c3 100644 --- a/test/cases/compile_errors/export_function_with_comptime_parameter.zig +++ b/test/cases/compile_errors/export_function_with_comptime_parameter.zig @@ -6,4 +6,4 @@ export fn foo(comptime x: anytype, y: i32) i32 { // backend=stage2 // target=native // -// :1:27: error: comptime parameters not allowed in function with calling convention 'C' +// :1:15: error: comptime parameters not allowed in function with calling convention 'C' diff --git a/test/cases/compile_errors/export_generic_function.zig b/test/cases/compile_errors/export_generic_function.zig index 65469be6d9..4ffbad9df7 100644 --- a/test/cases/compile_errors/export_generic_function.zig +++ b/test/cases/compile_errors/export_generic_function.zig @@ -7,4 +7,4 @@ export fn foo(num: anytype) i32 { // backend=stage2 // target=native // -// :1:20: error: generic parameters not allowed in function with calling convention 'C' +// :1:15: error: generic parameters not allowed in function with calling convention 'C' diff --git a/test/cases/compile_errors/extern_function_with_comptime_parameter.zig b/test/cases/compile_errors/extern_function_with_comptime_parameter.zig index b8f5f0b1b8..fac09cc265 100644 --- a/test/cases/compile_errors/extern_function_with_comptime_parameter.zig +++ b/test/cases/compile_errors/extern_function_with_comptime_parameter.zig @@ -19,5 +19,5 @@ comptime { // target=native // // :5:30: error: comptime parameters not allowed in function with calling convention 'C' -// :6:41: error: generic parameters not allowed in function with calling convention 'C' +// :6:30: error: generic parameters not allowed in function with calling convention 'C' // :1:15: error: comptime parameters not allowed in function with calling convention 'C' diff --git a/test/cases/compile_errors/missing_field_in_struct_value_expression.zig b/test/cases/compile_errors/missing_field_in_struct_value_expression.zig index d0b09643b8..3b09df106f 100644 --- a/test/cases/compile_errors/missing_field_in_struct_value_expression.zig +++ b/test/cases/compile_errors/missing_field_in_struct_value_expression.zig @@ -27,9 +27,9 @@ export fn h() void { // target=native // // :9:16: error: missing struct field: x -// :1:11: note: struct 'tmp.A' declared here +// :1:11: note: struct declared here // :18:16: error: missing tuple field with index 1 // :16:11: note: struct declared here // :22:16: error: missing tuple field with index 0 // :22:16: note: missing tuple field with index 1 -// :16:11: note: struct 'tmp.B' declared here +// :16:11: note: struct declared here diff --git a/test/cases/compile_errors/missing_struct_field_in_fn_called_at_comptime.zig b/test/cases/compile_errors/missing_struct_field_in_fn_called_at_comptime.zig index 1f3c4583cb..aaded91209 100644 --- a/test/cases/compile_errors/missing_struct_field_in_fn_called_at_comptime.zig +++ b/test/cases/compile_errors/missing_struct_field_in_fn_called_at_comptime.zig @@ -14,5 +14,5 @@ comptime { // target=native // // :5:17: error: missing struct field: b -// :1:11: note: struct 'tmp.S' declared here +// :1:11: note: struct declared here // :9:15: note: called from here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig index 0ea0b019b9..25b58e7c29 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig @@ -31,5 +31,3 @@ export fn entry() void { // target=native // // :13:16: error: enum fields missing in union -// :1:13: note: field 'arst' missing, declared here -// :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig index ed6f2245d4..dd324f751c 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig @@ -31,4 +31,3 @@ export fn entry() void { // target=native // // :12:16: error: no field named 'arst' in enum 'tmp.Tag' -// :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig index 91c5354c0c..188b4d9d6a 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig @@ -27,4 +27,3 @@ export fn entry() void { // target=native // // :9:16: error: no field named 'signed' in enum 'tmp.Tag' -// :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig index 2dc9832470..5c367e9ba6 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig @@ -27,6 +27,3 @@ export fn entry() void { // target=native // // :12:16: error: enum fields missing in union -// :1:13: note: field 'signed' missing, declared here -// :1:13: note: field 'unsigned' missing, declared here -// :1:13: note: enum declared here diff --git a/test/cases/compile_errors/switch_ranges_endpoints_are_validated.zig b/test/cases/compile_errors/switch_ranges_endpoints_are_validated.zig index b32e707ebd..fd4cd53364 100644 --- a/test/cases/compile_errors/switch_ranges_endpoints_are_validated.zig +++ b/test/cases/compile_errors/switch_ranges_endpoints_are_validated.zig @@ -17,5 +17,5 @@ pub export fn entr2() void { // backend=stage2 // target=native // -// :4:9: error: range start value is greater than the end value -// :11:9: error: range start value is greater than the end value +// :4:10: error: range start value is greater than the end value +// :11:11: error: range start value is greater than the end value diff --git a/test/cases/compile_errors/union_auto-enum_value_already_taken.zig b/test/cases/compile_errors/union_auto-enum_value_already_taken.zig index 31a027b7c0..d251b38c54 100644 --- a/test/cases/compile_errors/union_auto-enum_value_already_taken.zig +++ b/test/cases/compile_errors/union_auto-enum_value_already_taken.zig @@ -14,5 +14,5 @@ export fn entry() void { // backend=stage2 // target=native // -// :6:5: error: enum tag value 60 already taken -// :4:5: note: other occurrence here +// :6:9: error: enum tag value 60 already taken +// :4:9: note: other occurrence here