From e39cc0dff7fff510c3d72f61947b977589ea5583 Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 10 Jun 2024 01:22:54 +0100 Subject: [PATCH 01/10] Zir: use absolute nodes for declarations and type declarations The justification for using relative source nodes in ZIR is that it allows source locations -- which may be serialized across incremental updates -- to be relative to the source location of their containing declaration. However, having those "baseline" instructions themselves be relative to their own parent is counterproductive, since the source location updating problem is only being moved to `Decl`. Storing the absolute node here instead makes more sense, since it allows for this source location update logic to be elided entirely in the future by storing a `TrackedInst.Index` to resolve a source location relative to rather than a `Decl.Index`. --- lib/std/zig/AstGen.zig | 37 +++++++++++++++------- lib/std/zig/Zir.zig | 37 +++++++++++++++------- src/Module.zig | 13 ++++---- src/Sema.zig | 63 +++++++++++++++++++------------------ src/print_zir.zig | 71 ++++++++++++++++++++---------------------- 5 files changed, 123 insertions(+), 98 deletions(-) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index f02dcaa2db27..b356789bfda8 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -4011,7 +4011,7 @@ fn fnDecl( // We insert this at the beginning so that its instruction index marks the // start of the top level declaration. - const decl_inst = try gz.makeBlockInst(.declaration, fn_proto.ast.proto_node); + const decl_inst = try gz.makeDeclaration(fn_proto.ast.proto_node); astgen.advanceSourceCursorToNode(decl_node); var decl_gz: GenZir = .{ @@ -4393,7 +4393,7 @@ fn globalVarDecl( const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; // We do this at the beginning so that the instruction index marks the range start // of the top level declaration. - const decl_inst = try gz.makeBlockInst(.declaration, node); + const decl_inst = try gz.makeDeclaration(node); const name_token = var_decl.ast.mut_token + 1; astgen.advanceSourceCursorToNode(node); @@ -4555,7 +4555,7 @@ fn comptimeDecl( // Up top so the ZIR instruction index marks the start range of this // top-level declaration. - const decl_inst = try gz.makeBlockInst(.declaration, node); + const decl_inst = try gz.makeDeclaration(node); wip_members.nextDecl(decl_inst); astgen.advanceSourceCursorToNode(node); @@ -4607,7 +4607,7 @@ fn usingnamespaceDecl( }; // Up top so the ZIR instruction index marks the start range of this // top-level declaration. - const decl_inst = try gz.makeBlockInst(.declaration, node); + const decl_inst = try gz.makeDeclaration(node); wip_members.nextDecl(decl_inst); astgen.advanceSourceCursorToNode(node); @@ -4651,7 +4651,7 @@ fn testDecl( // Up top so the ZIR instruction index marks the start range of this // top-level declaration. - const decl_inst = try gz.makeBlockInst(.declaration, node); + const decl_inst = try gz.makeDeclaration(node); wip_members.nextDecl(decl_inst); astgen.advanceSourceCursorToNode(node); @@ -13071,6 +13071,21 @@ const GenZir = struct { return new_index; } + /// Note that this returns a `Zir.Inst.Index` not a ref. + /// Does *not* append the block instruction to the scope. + /// Leaves the `payload_index` field undefined. Use `setDeclaration` to finalize. + fn makeDeclaration(gz: *GenZir, node: Ast.Node.Index) !Zir.Inst.Index { + const new_index: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len); + try gz.astgen.instructions.append(gz.astgen.gpa, .{ + .tag = .declaration, + .data = .{ .declaration = .{ + .src_node = node, + .payload_index = undefined, + } }, + }); + return new_index; + } + /// Note that this returns a `Zir.Inst.Index` not a ref. /// Leaves the `payload_index` field undefined. fn addCondBr(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index { @@ -13117,7 +13132,7 @@ const GenZir = struct { .fields_hash_1 = fields_hash_arr[1], .fields_hash_2 = fields_hash_arr[2], .fields_hash_3 = fields_hash_arr[3], - .src_node = gz.nodeIndexToRelative(args.src_node), + .src_node = args.src_node, }); if (args.captures_len != 0) { @@ -13177,7 +13192,7 @@ const GenZir = struct { .fields_hash_1 = fields_hash_arr[1], .fields_hash_2 = fields_hash_arr[2], .fields_hash_3 = fields_hash_arr[3], - .src_node = gz.nodeIndexToRelative(args.src_node), + .src_node = args.src_node, }); if (args.tag_type != .none) { @@ -13238,7 +13253,7 @@ const GenZir = struct { .fields_hash_1 = fields_hash_arr[1], .fields_hash_2 = fields_hash_arr[2], .fields_hash_3 = fields_hash_arr[3], - .src_node = gz.nodeIndexToRelative(args.src_node), + .src_node = args.src_node, }); if (args.tag_type != .none) { @@ -13285,9 +13300,7 @@ const GenZir = struct { assert(args.src_node != 0); try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 2); - const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ - .src_node = gz.nodeIndexToRelative(args.src_node), - }); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ .src_node = args.src_node }); if (args.captures_len != 0) { astgen.extra.appendAssumeCapacity(args.captures_len); @@ -13897,7 +13910,7 @@ fn setDeclaration( .has_align_linksection_addrspace = align_len != 0 or linksection_len != 0 or addrspace_len != 0, }, }; - astgen.instructions.items(.data)[@intFromEnum(decl_inst)].pl_node.payload_index = try astgen.addExtra(extra); + astgen.instructions.items(.data)[@intFromEnum(decl_inst)].declaration.payload_index = try astgen.addExtra(extra); if (extra.flags.has_doc_comment) { try astgen.extra.append(gpa, @intFromEnum(true_doc_comment)); } diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index a79e965fe923..1ab7e94842ee 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -287,7 +287,7 @@ pub const Inst = struct { /// namespace type, e.g. within a `struct_decl` instruction. It represents a /// single source declaration (`const`/`var`/`fn`), containing the name, /// attributes, type, and value of the declaration. - /// Uses the `pl_node` union field. Payload is `Declaration`. + /// Uses the `declaration` union field. Payload is `Declaration`. declaration, /// Implements `suspend {...}`. /// Uses the `pl_node` union field. Payload is `Block`. @@ -1596,7 +1596,7 @@ pub const Inst = struct { .block = .pl_node, .block_comptime = .pl_node, .block_inline = .pl_node, - .declaration = .pl_node, + .declaration = .declaration, .suspend_block = .pl_node, .bool_not = .un_node, .bool_br_and = .pl_node, @@ -2370,6 +2370,16 @@ pub const Inst = struct { /// The index being accessed. idx: u32, }, + declaration: struct { + /// This node provides a new absolute baseline node for all instructions within this struct. + src_node: Ast.Node.Index, + /// index into extra to a `Declaration` payload. + payload_index: u32, + + pub fn src(self: @This()) LazySrcLoc { + return .{ .node_abs = self.src_node }; + } + }, // Make sure we don't accidentally add a field to make this union // bigger than expected. Note that in Debug builds, Zig is allowed @@ -2408,6 +2418,7 @@ pub const Inst = struct { defer_err_code, save_err_ret_index, elem_val_imm, + declaration, }; }; @@ -3018,10 +3029,11 @@ pub const Inst = struct { fields_hash_1: u32, fields_hash_2: u32, fields_hash_3: u32, - src_node: i32, + /// This node provides a new absolute baseline node for all instructions within this struct. + src_node: Ast.Node.Index, pub fn src(self: StructDecl) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); + return .{ .node_abs = self.src_node }; } pub const Small = packed struct { @@ -3150,10 +3162,11 @@ pub const Inst = struct { fields_hash_1: u32, fields_hash_2: u32, fields_hash_3: u32, - src_node: i32, + /// This node provides a new absolute baseline node for all instructions within this struct. + src_node: Ast.Node.Index, pub fn src(self: EnumDecl) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); + return .{ .node_abs = self.src_node }; } pub const Small = packed struct { @@ -3198,10 +3211,11 @@ pub const Inst = struct { fields_hash_1: u32, fields_hash_2: u32, fields_hash_3: u32, - src_node: i32, + /// This node provides a new absolute baseline node for all instructions within this struct. + src_node: Ast.Node.Index, pub fn src(self: UnionDecl) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); + return .{ .node_abs = self.src_node }; } pub const Small = packed struct { @@ -3230,10 +3244,11 @@ pub const Inst = struct { /// 2. capture: Capture, // for every captures_len /// 3. decl: Index, // for every decls_len; points to a `declaration` instruction pub const OpaqueDecl = struct { - src_node: i32, + /// This node provides a new absolute baseline node for all instructions within this struct. + src_node: Ast.Node.Index, pub fn src(self: OpaqueDecl) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); + return .{ .node_abs = self.src_node }; } pub const Small = packed struct { @@ -4046,7 +4061,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) struct { Inst.Declaration, u32 } { assert(zir.instructions.items(.tag)[@intFromEnum(inst)] == .declaration); - const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].pl_node; + const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].declaration; const extra = zir.extraData(Inst.Declaration, pl_node.payload_index); return .{ extra.data, diff --git a/src/Module.zig b/src/Module.zig index ef410fad4e33..83406c36a4cd 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -413,8 +413,8 @@ pub const Decl = struct { pub fn zirBodies(decl: Decl, zcu: *Zcu) Zir.Inst.Declaration.Bodies { const zir = decl.getFileScope(zcu).zir; const zir_index = decl.zir_decl_index.unwrap().?.resolve(&zcu.intern_pool); - const pl_node = zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; - const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); + const declaration = zir.instructions.items(.data)[@intFromEnum(zir_index)].declaration; + const extra = zir.extraData(Zir.Inst.Declaration, declaration.payload_index); return extra.data.getBodies(@intCast(extra.end), zir); } @@ -4255,12 +4255,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void const zir = namespace.file_scope.zir; const ip = &zcu.intern_pool; - const pl_node = zir.instructions.items(.data)[@intFromEnum(decl_inst)].pl_node; - const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); + const inst_data = zir.instructions.items(.data)[@intFromEnum(decl_inst)].declaration; + const extra = zir.extraData(Zir.Inst.Declaration, inst_data.payload_index); const declaration = extra.data; const line = iter.parent_decl.src_line + declaration.line_offset; - const decl_node = iter.parent_decl.relativeToNodeIndex(pl_node.src_node); // Every Decl needs a name. const decl_name: InternPool.NullTerminatedString, const kind: Decl.Kind, const is_named_test: bool = switch (declaration.name) { @@ -4348,14 +4347,14 @@ 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 = decl_node; + 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, decl_node); + const new_decl_index = try zcu.allocateNewDecl(namespace_index, inst_data.src_node); const new_decl = zcu.declPtr(new_decl_index); new_decl.kind = kind; new_decl.name = decl_name; diff --git a/src/Sema.zig b/src/Sema.zig index 2fcf1261a21b..257f27d11ae0 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2835,7 +2835,7 @@ fn zirStructDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - src, + extra.data.src_node, Value.fromInterned(wip_ty.index), small.name_strategy, "struct", @@ -2872,7 +2872,7 @@ fn zirStructDecl( fn createAnonymousDeclTypeNamed( sema: *Sema, block: *Block, - src: LazySrcLoc, + src_node: std.zig.Ast.Node.Index, val: Value, name_strategy: Zir.Inst.NameStrategy, anon_prefix: []const u8, @@ -2883,31 +2883,17 @@ fn createAnonymousDeclTypeNamed( const gpa = sema.gpa; const namespace = block.namespace; const src_decl = zcu.declPtr(block.src_decl); - const src_node = src_decl.relativeToNodeIndex(src.node_offset.x); const new_decl_index = try zcu.allocateNewDecl(namespace, src_node); errdefer zcu.destroyDecl(new_decl_index); switch (name_strategy) { - .anon => { - // It would be neat to have "struct:line:column" but this name has - // to survive incremental updates, where it may have been shifted down - // or up to a different line, but unchanged, and thus not unnecessarily - // semantically analyzed. - // This name is also used as the key in the parent namespace so it cannot be - // renamed. - - const name = ip.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ - src_decl.name.fmt(ip), anon_prefix, @intFromEnum(new_decl_index), - }, .no_embedded_nulls) catch unreachable; - try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); - return new_decl_index; - }, + .anon => {}, // handled after switch .parent => { const name = zcu.declPtr(block.src_decl).name; try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); return new_decl_index; }, - .func => { + .func => func_strat: { const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip)); const zir_tags = sema.code.instructions.items(.tag); @@ -2927,7 +2913,7 @@ fn createAnonymousDeclTypeNamed( // 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 - return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null); + break :func_strat; // fall through to anon strat if (arg_i != 0) try writer.writeByte(','); @@ -2969,9 +2955,24 @@ fn createAnonymousDeclTypeNamed( }, else => {}, }; - return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null); + // fall through to anon strat }, } + + // anon strat handling. + + // It would be neat to have "struct:line:column" but this name has + // to survive incremental updates, where it may have been shifted down + // or up to a different line, but unchanged, and thus not unnecessarily + // semantically analyzed. + // This name is also used as the key in the parent namespace so it cannot be + // renamed. + + const name = ip.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ + src_decl.name.fmt(ip), anon_prefix, @intFromEnum(new_decl_index), + }, .no_embedded_nulls) catch unreachable; + try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); + return new_decl_index; } fn zirEnumDecl( @@ -2991,7 +2992,6 @@ fn zirEnumDecl( var extra_index: usize = extra.end; const src = extra.data.src(); - const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x }; const tag_type_ref = if (small.has_tag_type) blk: { const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); @@ -3071,7 +3071,7 @@ fn zirEnumDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - src, + extra.data.src_node, Value.fromInterned(wip_ty.index), small.name_strategy, "enum", @@ -3140,14 +3140,17 @@ fn zirEnumDecl( }; 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); } if (tag_type_ref != .none) { - const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); + const ty = try sema.resolveType(&enum_block, tag_ty_src, tag_type_ref); if (ty.zigTypeTag(mod) != .Int and ty.zigTypeTag(mod) != .ComptimeInt) { - return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); + return sema.fail(&enum_block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); } break :ty ty; } else if (fields_len == 0) { @@ -3342,7 +3345,7 @@ fn zirUnionDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - src, + extra.data.src_node, Value.fromInterned(wip_ty.index), small.name_strategy, "union", @@ -3430,7 +3433,7 @@ fn zirOpaqueDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - src, + extra.data.src_node, Value.fromInterned(wip_ty.index), small.name_strategy, "opaque", @@ -21658,7 +21661,7 @@ fn zirReify( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - src, + mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x), Value.fromInterned(wip_ty.index), name_strategy, "opaque", @@ -21858,7 +21861,7 @@ fn reifyEnum( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - src, + mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x), Value.fromInterned(wip_ty.index), name_strategy, "enum", @@ -22005,7 +22008,7 @@ fn reifyUnion( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - src, + mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x), Value.fromInterned(wip_ty.index), name_strategy, "union", @@ -22264,7 +22267,7 @@ fn reifyStruct( const new_decl_index = try sema.createAnonymousDeclTypeNamed( block, - src, + mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x), Value.fromInterned(wip_ty.index), name_strategy, "struct", diff --git a/src/print_zir.zig b/src/print_zir.zig index 4a262c4ada8f..d5772949eb95 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -1390,9 +1390,14 @@ const Writer = struct { } fn writeStructDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { - const small = @as(Zir.Inst.StructDecl.Small, @bitCast(extended.small)); + const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand); + + const prev_parent_decl_node = self.parent_decl_node; + self.parent_decl_node = extra.data.src_node; + defer self.parent_decl_node = prev_parent_decl_node; + const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ extra.data.fields_hash_0, extra.data.fields_hash_1, @@ -1465,10 +1470,6 @@ const Writer = struct { if (decls_len == 0) { try stream.writeAll("{}, "); } else { - const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node); - defer self.parent_decl_node = prev_parent_decl_node; - try stream.writeAll("{\n"); self.indent += 2; try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); @@ -1546,8 +1547,6 @@ const Writer = struct { } } - const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node); try stream.writeAll("{\n"); self.indent += 2; @@ -1595,18 +1594,22 @@ const Writer = struct { try stream.writeAll(",\n"); } - self.parent_decl_node = prev_parent_decl_node; self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); try stream.writeAll("})"); } - try self.writeSrcNode(stream, extra.data.src_node); + try self.writeSrcNode(stream, 0); } fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand); + + const prev_parent_decl_node = self.parent_decl_node; + self.parent_decl_node = extra.data.src_node; + defer self.parent_decl_node = prev_parent_decl_node; + const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ extra.data.fields_hash_0, extra.data.fields_hash_1, @@ -1670,10 +1673,6 @@ const Writer = struct { if (decls_len == 0) { try stream.writeAll("{}"); } else { - const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node); - defer self.parent_decl_node = prev_parent_decl_node; - try stream.writeAll("{\n"); self.indent += 2; try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); @@ -1690,7 +1689,7 @@ const Writer = struct { if (fields_len == 0) { try stream.writeAll("})"); - try self.writeSrcNode(stream, extra.data.src_node); + try self.writeSrcNode(stream, 0); return; } try stream.writeAll(", "); @@ -1698,8 +1697,6 @@ const Writer = struct { const body = self.code.bodySlice(extra_index, body_len); extra_index += body.len; - const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node); try self.writeBracedDecl(stream, body); try stream.writeAll(", {\n"); @@ -1763,17 +1760,21 @@ const Writer = struct { try stream.writeAll(",\n"); } - self.parent_decl_node = prev_parent_decl_node; self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); try stream.writeAll("})"); - try self.writeSrcNode(stream, extra.data.src_node); + try self.writeSrcNode(stream, 0); } fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand); + + const prev_parent_decl_node = self.parent_decl_node; + self.parent_decl_node = extra.data.src_node; + defer self.parent_decl_node = prev_parent_decl_node; + const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ extra.data.fields_hash_0, extra.data.fields_hash_1, @@ -1835,10 +1836,6 @@ const Writer = struct { if (decls_len == 0) { try stream.writeAll("{}, "); } else { - const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node); - defer self.parent_decl_node = prev_parent_decl_node; - try stream.writeAll("{\n"); self.indent += 2; try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); @@ -1856,12 +1853,9 @@ const Writer = struct { const body = self.code.bodySlice(extra_index, body_len); extra_index += body.len; - const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node); try self.writeBracedDecl(stream, body); if (fields_len == 0) { try stream.writeAll(", {})"); - self.parent_decl_node = prev_parent_decl_node; } else { try stream.writeAll(", {\n"); @@ -1900,12 +1894,11 @@ const Writer = struct { } try stream.writeAll(",\n"); } - self.parent_decl_node = prev_parent_decl_node; self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); try stream.writeAll("})"); } - try self.writeSrcNode(stream, extra.data.src_node); + try self.writeSrcNode(stream, 0); } fn writeOpaqueDecl( @@ -1915,6 +1908,11 @@ const Writer = struct { ) !void { const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small)); const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); + + const prev_parent_decl_node = self.parent_decl_node; + self.parent_decl_node = extra.data.src_node; + defer self.parent_decl_node = prev_parent_decl_node; + var extra_index: usize = extra.end; const captures_len = if (small.has_captures_len) blk: { @@ -1948,10 +1946,6 @@ const Writer = struct { if (decls_len == 0) { try stream.writeAll("{})"); } else { - const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node); - defer self.parent_decl_node = prev_parent_decl_node; - try stream.writeAll("{\n"); self.indent += 2; try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); @@ -1959,7 +1953,7 @@ const Writer = struct { try stream.writeByteNTimes(' ', self.indent); try stream.writeAll("})"); } - try self.writeSrcNode(stream, extra.data.src_node); + try self.writeSrcNode(stream, 0); } fn writeErrorSetDecl( @@ -2729,11 +2723,16 @@ const Writer = struct { } fn writeDeclaration(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { - const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; + const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].declaration; const extra = self.code.extraData(Zir.Inst.Declaration, inst_data.payload_index); const doc_comment: ?Zir.NullTerminatedString = if (extra.data.flags.has_doc_comment) dc: { break :dc @enumFromInt(self.code.extra[extra.end]); } else null; + + const prev_parent_decl_node = self.parent_decl_node; + defer self.parent_decl_node = prev_parent_decl_node; + self.parent_decl_node = inst_data.src_node; + if (extra.data.flags.is_pub) try stream.writeAll("pub "); if (extra.data.flags.is_export) try stream.writeAll("export "); switch (extra.data.name) { @@ -2757,10 +2756,6 @@ const Writer = struct { try stream.print(" line(+{d}) hash({})", .{ extra.data.line_offset, std.fmt.fmtSliceHexLower(&src_hash_bytes) }); { - const prev_parent_decl_node = self.parent_decl_node; - defer self.parent_decl_node = prev_parent_decl_node; - self.parent_decl_node = self.relativeToNodeIndex(inst_data.src_node); - const bodies = extra.data.getBodies(@intCast(extra.end), self.code); try stream.writeAll(" value="); @@ -2783,7 +2778,7 @@ const Writer = struct { } try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, 0); } fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { From 07a24bec9a578857920f4c5508f1d7eea65177b8 Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 11 Jun 2024 21:00:39 +0100 Subject: [PATCH 02/10] compiler: move LazySrcLoc out of std This is in preparation for some upcoming changes to how we represent source locations in the compiler. The bulk of the change here is dealing with the removal of `src()` methods from `Zir` types. --- lib/std/zig.zig | 373 ------------------------------- lib/std/zig/Zir.zig | 61 ----- src/InternPool.zig | 23 +- src/Module.zig | 352 ++++++++++++++++++++++++++++- src/Sema.zig | 348 ++++++++++++++-------------- src/Sema/comptime_ptr_access.zig | 3 +- src/arch/wasm/CodeGen.zig | 2 +- src/codegen/c.zig | 2 +- src/codegen/c/Type.zig | 2 +- src/codegen/llvm.zig | 2 +- src/codegen/spirv.zig | 2 +- src/print_zir.zig | 141 ++++++------ 12 files changed, 632 insertions(+), 679 deletions(-) diff --git a/lib/std/zig.zig b/lib/std/zig.zig index f0bcc974f620..230dc45ddcbd 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -350,379 +350,6 @@ pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![ return buffer.toOwnedSlice(); } -pub const DeclIndex = enum(u32) { - _, - - pub fn toOptional(i: DeclIndex) OptionalDeclIndex { - return @enumFromInt(@intFromEnum(i)); - } -}; - -pub const OptionalDeclIndex = enum(u32) { - none = std.math.maxInt(u32), - _, - - pub fn init(oi: ?DeclIndex) OptionalDeclIndex { - return @enumFromInt(@intFromEnum(oi orelse return .none)); - } - - pub fn unwrap(oi: OptionalDeclIndex) ?DeclIndex { - if (oi == .none) return null; - return @enumFromInt(@intFromEnum(oi)); - } -}; - -/// 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: DeclIndex, - /// 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: DeclIndex, - /// 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, - - 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) 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; - }; -}; - const std = @import("std.zig"); const tokenizer = @import("zig/tokenizer.zig"); const assert = std.debug.assert; diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 1ab7e94842ee..beead16e3761 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -20,7 +20,6 @@ const BigIntMutable = std.math.big.int.Mutable; const Ast = std.zig.Ast; const Zir = @This(); -const LazySrcLoc = std.zig.LazySrcLoc; instructions: std.MultiArrayList(Inst).Slice, /// In order to store references to strings in fewer bytes, we copy all @@ -2221,10 +2220,6 @@ pub const Inst = struct { src_node: i32, /// The meaning of this operand depends on the corresponding `Tag`. operand: Ref, - - pub fn src(self: @This()) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); - } }, /// Used for unary operators, with a token source location. un_tok: struct { @@ -2232,10 +2227,6 @@ pub const Inst = struct { src_tok: Ast.TokenIndex, /// The meaning of this operand depends on the corresponding `Tag`. operand: Ref, - - pub fn src(self: @This()) LazySrcLoc { - return .{ .token_offset = self.src_tok }; - } }, pl_node: struct { /// Offset from Decl AST node index. @@ -2244,10 +2235,6 @@ pub const Inst = struct { /// index into extra. /// `Tag` determines what lives there. payload_index: u32, - - pub fn src(self: @This()) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); - } }, pl_tok: struct { /// Offset from Decl AST token index. @@ -2255,10 +2242,6 @@ pub const Inst = struct { /// index into extra. /// `Tag` determines what lives there. payload_index: u32, - - pub fn src(self: @This()) LazySrcLoc { - return .{ .token_offset = self.src_tok }; - } }, bin: Bin, /// For strings which may contain null bytes. @@ -2281,10 +2264,6 @@ pub const Inst = struct { pub fn get(self: @This(), code: Zir) [:0]const u8 { return code.nullTerminatedString(self.start); } - - pub fn src(self: @This()) LazySrcLoc { - return .{ .token_offset = self.src_tok }; - } }, /// Offset from Decl AST token index. tok: Ast.TokenIndex, @@ -2313,19 +2292,11 @@ pub const Inst = struct { src_node: i32, signedness: std.builtin.Signedness, bit_count: u16, - - pub fn src(self: @This()) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); - } }, @"unreachable": struct { /// Offset from Decl AST node index. /// `Tag` determines which kind of AST node this points to. src_node: i32, - - pub fn src(self: @This()) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); - } }, @"break": struct { operand: Ref, @@ -2339,10 +2310,6 @@ pub const Inst = struct { src_node: i32, /// The meaning of this operand depends on the corresponding `Tag`. inst: Index, - - pub fn src(self: @This()) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); - } }, str_op: struct { /// Offset into `string_bytes`. Null-terminated. @@ -2375,10 +2342,6 @@ pub const Inst = struct { src_node: Ast.Node.Index, /// index into extra to a `Declaration` payload. payload_index: u32, - - pub fn src(self: @This()) LazySrcLoc { - return .{ .node_abs = self.src_node }; - } }, // Make sure we don't accidentally add a field to make this union @@ -3032,10 +2995,6 @@ pub const Inst = struct { /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, - pub fn src(self: StructDecl) LazySrcLoc { - return .{ .node_abs = self.src_node }; - } - pub const Small = packed struct { has_captures_len: bool, has_fields_len: bool, @@ -3165,10 +3124,6 @@ pub const Inst = struct { /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, - pub fn src(self: EnumDecl) LazySrcLoc { - return .{ .node_abs = self.src_node }; - } - pub const Small = packed struct { has_tag_type: bool, has_captures_len: bool, @@ -3214,10 +3169,6 @@ pub const Inst = struct { /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, - pub fn src(self: UnionDecl) LazySrcLoc { - return .{ .node_abs = self.src_node }; - } - pub const Small = packed struct { has_tag_type: bool, has_captures_len: bool, @@ -3247,10 +3198,6 @@ pub const Inst = struct { /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, - pub fn src(self: OpaqueDecl) LazySrcLoc { - return .{ .node_abs = self.src_node }; - } - pub const Small = packed struct { has_captures_len: bool, has_decls_len: bool, @@ -3367,10 +3314,6 @@ pub const Inst = struct { parent_ptr_type: Ref, field_name: Ref, field_ptr: Ref, - - pub fn src(self: FieldParentPtr) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); - } }; pub const Shuffle = struct { @@ -3520,10 +3463,6 @@ pub const Inst = struct { block: Ref, /// If `.none`, restore unconditionally. operand: Ref, - - pub fn src(self: RestoreErrRetIndex) LazySrcLoc { - return LazySrcLoc.nodeOffset(self.src_node); - } }; }; diff --git a/src/InternPool.zig b/src/InternPool.zig index b6d5e77f53ed..f1c90311c431 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -391,8 +391,27 @@ pub const RuntimeIndex = enum(u32) { pub const ComptimeAllocIndex = enum(u32) { _ }; -pub const DeclIndex = std.zig.DeclIndex; -pub const OptionalDeclIndex = std.zig.OptionalDeclIndex; +pub const DeclIndex = enum(u32) { + _, + + pub fn toOptional(i: DeclIndex) OptionalDeclIndex { + return @enumFromInt(@intFromEnum(i)); + } +}; + +pub const OptionalDeclIndex = enum(u32) { + none = std.math.maxInt(u32), + _, + + pub fn init(oi: ?DeclIndex) OptionalDeclIndex { + return @enumFromInt(@intFromEnum(oi orelse return .none)); + } + + pub fn unwrap(oi: OptionalDeclIndex) ?DeclIndex { + if (oi == .none) return null; + return @enumFromInt(@intFromEnum(oi)); + } +}; pub const NamespaceIndex = enum(u32) { _, diff --git a/src/Module.zig b/src/Module.zig index 83406c36a4cd..283a4f75cc48 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -13,7 +13,6 @@ const BigIntConst = std.math.big.int.Const; const BigIntMutable = std.math.big.int.Mutable; const Target = std.Target; const Ast = std.zig.Ast; -const LazySrcLoc = std.zig.LazySrcLoc; /// Deprecated, use `Zcu`. const Module = Zcu; @@ -1905,6 +1904,357 @@ pub const SrcLoc = struct { } }; +/// 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, + + 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) 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 SemaError = error{ OutOfMemory, AnalysisFail }; pub const CompileError = error{ OutOfMemory, diff --git a/src/Sema.zig b/src/Sema.zig index 257f27d11ae0..eacc4e097dc3 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -182,7 +182,7 @@ const Namespace = Module.Namespace; const CompileError = Module.CompileError; const SemaError = Module.SemaError; const Decl = Module.Decl; -const LazySrcLoc = std.zig.LazySrcLoc; +const LazySrcLoc = Zcu.LazySrcLoc; const RangeSet = @import("RangeSet.zig"); const target_util = @import("target.zig"); const Package = @import("Package.zig"); @@ -395,6 +395,18 @@ 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! + + fn nodeOffset(block: Block, node_offset: i32) LazySrcLoc { + _ = block; + return LazySrcLoc.nodeOffset(node_offset); + } + + fn tokenOffset(block: Block, tok_offset: u32) LazySrcLoc { + _ = block; + return .{ .token_offset = tok_offset }; + } + const ComptimeReason = union(enum) { c_import: struct { block: *Block, @@ -1449,7 +1461,7 @@ fn analyzeBodyInner( .check_comptime_control_flow => { if (!block.is_comptime) { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const inline_block = inst_data.operand.toIndex().?; var check_block = block; @@ -1482,13 +1494,13 @@ fn analyzeBodyInner( }, .restore_err_ret_index_unconditional => { const un_node = datas[@intFromEnum(inst)].un_node; - try sema.restoreErrRetIndex(block, un_node.src(), un_node.operand, .none); + try sema.restoreErrRetIndex(block, block.nodeOffset(un_node.src_node), un_node.operand, .none); i += 1; continue; }, .restore_err_ret_index_fn_entry => { const un_node = datas[@intFromEnum(inst)].un_node; - try sema.restoreErrRetIndex(block, un_node.src(), .none, un_node.operand); + try sema.restoreErrRetIndex(block, block.nodeOffset(un_node.src_node), .none, un_node.operand); i += 1; continue; }, @@ -1667,7 +1679,7 @@ fn analyzeBodyInner( try labeled_block.block.instructions.appendSlice(gpa, block.instructions.items[block_index..]); block.instructions.items.len = block_index; - const block_result = try sema.resolveAnalyzedBlock(block, inst_data.src(), &labeled_block.block, &labeled_block.label.merges, need_debug_scope); + const block_result = try sema.resolveAnalyzedBlock(block, block.nodeOffset(inst_data.src_node), &labeled_block.block, &labeled_block.label.merges, need_debug_scope); { // Destroy the ad-hoc block entry so that it does not interfere with // the next iteration of comptime control flow, if any. @@ -1736,7 +1748,7 @@ fn analyzeBodyInner( .@"try" => blk: { 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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .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); @@ -1762,7 +1774,7 @@ fn analyzeBodyInner( .try_ptr => blk: { 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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .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); @@ -1929,7 +1941,7 @@ fn resolveDestType( const msg = msg: { const msg = try sema.errMsg(block, src, "{s} must have a known result type", .{builtin_name}); errdefer msg.destroy(sema.gpa); - switch (sema.genericPoisonReason(zir_ref)) { + 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", .{}), .unknown => {}, @@ -1963,7 +1975,7 @@ const GenericPoisonReason = union(enum) { /// Backtracks through ZIR instructions to determine the reason a generic poison /// type was created. Used for error reporting. -fn genericPoisonReason(sema: *Sema, ref: Zir.Inst.Ref) GenericPoisonReason { +fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoisonReason { var cur = ref; while (true) { const inst = cur.toIndex() orelse return .unknown; @@ -1999,7 +2011,7 @@ fn genericPoisonReason(sema: *Sema, ref: Zir.Inst.Ref) GenericPoisonReason { cur = un_node.operand; } else { // This must be an anyopaque pointer! - return .{ .anyopaque_ptr = un_node.src() }; + return .{ .anyopaque_ptr = block.nodeOffset(un_node.src_node) }; } }, .call, .field_call => { @@ -2007,7 +2019,7 @@ fn genericPoisonReason(sema: *Sema, ref: Zir.Inst.Ref) GenericPoisonReason { // evaluating an `anytype` function parameter. // TODO: better source location - function decl rather than call const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - return .{ .anytype_param = pl_node.src() }; + return .{ .anytype_param = block.nodeOffset(pl_node.src_node) }; }, else => return .unknown, } @@ -2776,7 +2788,7 @@ 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 = extra.data.src(); + const src: LazySrcLoc = .{ .node_abs = extra.data.src_node }; var extra_index = extra.end; const captures_len = if (small.has_captures_len) blk: { @@ -2991,7 +3003,7 @@ fn zirEnumDecl( const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand); var extra_index: usize = extra.end; - const src = extra.data.src(); + const src: LazySrcLoc = .{ .node_abs = extra.data.src_node }; const tag_type_ref = if (small.has_tag_type) blk: { const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); @@ -3282,7 +3294,7 @@ fn zirUnionDecl( const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand); var extra_index: usize = extra.end; - const src = extra.data.src(); + const src: LazySrcLoc = .{ .node_abs = extra.data.src_node }; extra_index += @intFromBool(small.has_tag_type); const captures_len = if (small.has_captures_len) blk: { @@ -3397,7 +3409,7 @@ fn zirOpaqueDecl( const extra = sema.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); var extra_index: usize = extra.end; - const src = extra.data.src(); + const src: LazySrcLoc = .{ .node_abs = extra.data.src_node }; const captures_len = if (small.has_captures_len) blk: { const captures_len = sema.code.extra[extra_index]; @@ -3528,7 +3540,7 @@ fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; const operand = try sema.resolveInst(inst_data.operand); - return sema.analyzeRef(block, inst_data.src(), operand); + return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand); } fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { @@ -3537,7 +3549,7 @@ fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = try sema.resolveInst(inst_data.operand); - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); return sema.ensureResultUsed(block, sema.typeOf(operand), src); } @@ -3581,7 +3593,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com 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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_ty = sema.typeOf(operand); switch (operand_ty.zigTypeTag(mod)) { .ErrorSet => return sema.fail(block, src, "error set is discarded", .{}), @@ -3604,7 +3616,7 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const err_union_ty = if (operand_ty.zigTypeTag(mod) == .Pointer) @@ -3629,7 +3641,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const object = try sema.resolveInst(inst_data.operand); return indexablePtrLen(sema, block, src, object); @@ -4223,7 +4235,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com const mod = sema.mod; const gpa = sema.gpa; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; const ptr = try sema.resolveInst(inst_data.operand); const ptr_inst = ptr.toIndex().?; @@ -4364,7 +4376,7 @@ fn zirForLen(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.MultiOp, inst_data.payload_index); const args = sema.code.refSlice(extra.end, extra.data.operands_len); - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); var len: Air.Inst.Ref = .none; var len_val: ?Value = null; @@ -4507,13 +4519,13 @@ fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcL fn zirOptEuBasePtrInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ptr = try sema.resolveInst(un_node.operand); - return sema.optEuBasePtrInit(block, ptr, un_node.src()); + return sema.optEuBasePtrInit(block, ptr, block.nodeOffset(un_node.src_node)); } fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = pl_node.src(); + 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) { @@ -4564,7 +4576,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const mod = sema.mod; const un_tok = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; - const src = un_tok.src(); + const src = block.tokenOffset(un_tok.src_tok); // In case of GenericPoison, we don't actually have a type, so this will be // treated as an untyped address-of operator. const operand_air_inst = sema.resolveInst(un_tok.operand) catch |err| switch (err) { @@ -4593,7 +4605,7 @@ fn zirValidateArrayInitRefTy( ) CompileError!Air.Inst.Ref { const mod = sema.mod; const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = pl_node.src(); + 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) { error.GenericPoison => return .generic_poison_type, @@ -4635,7 +4647,7 @@ fn zirValidateArrayInitTy( ) CompileError!void { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + 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 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) { @@ -4698,7 +4710,7 @@ fn zirValidateStructInitTy( ) CompileError!void { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ty = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) { // It's okay for the type to be unknown: this will result in an anonymous struct init. error.GenericPoison => return, @@ -4723,7 +4735,7 @@ fn zirValidatePtrStructInit( const mod = sema.mod; const validate_inst = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const init_src = validate_inst.src(); + const init_src = block.nodeOffset(validate_inst.src_node); const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index); const instrs = sema.code.bodySlice(validate_extra.end, validate_extra.data.body_len); const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node; @@ -4898,11 +4910,11 @@ fn validateUnionInit( try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store); return; } else if (try sema.typeRequiresComptime(union_ty)) { - return sema.failWithNeededComptime(block, field_ptr_data.src(), .{ + return sema.failWithNeededComptime(block, block.nodeOffset(field_ptr_data.src_node), .{ .needed_comptime_reason = "initializer of comptime only union must be comptime-known", }); } - if (init_ref) |v| try sema.validateRuntimeValue(block, field_ptr_data.src(), v); + if (init_ref) |v| try sema.validateRuntimeValue(block, block.nodeOffset(field_ptr_data.src_node), v); const new_tag = Air.internedToRef(tag_val.toIntern()); const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, new_tag); @@ -5089,7 +5101,7 @@ fn validateStructInit( field_values[i] = val.toIntern(); } else if (require_comptime) { const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(field_ptr)].pl_node; - return sema.failWithNeededComptime(block, field_ptr_data.src(), .{ + return sema.failWithNeededComptime(block, block.nodeOffset(field_ptr_data.src_node), .{ .needed_comptime_reason = "initializer of comptime only struct must be comptime-known", }); } else { @@ -5213,7 +5225,7 @@ fn zirValidatePtrArrayInit( ) CompileError!void { const mod = sema.mod; const validate_inst = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const init_src = validate_inst.src(); + const init_src = block.nodeOffset(validate_inst.src_node); const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index); const instrs = sema.code.bodySlice(validate_extra.end, validate_extra.data.body_len); const first_elem_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node; @@ -5418,7 +5430,7 @@ fn zirValidatePtrArrayInit( fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); @@ -5462,7 +5474,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const mod = sema.mod; 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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const destructure_src = LazySrcLoc.nodeOffset(extra.destructure_node); const operand = try sema.resolveInst(extra.operand); const operand_ty = sema.typeOf(operand); @@ -5593,7 +5605,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi defer tracy.end(); const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = pl_node.src(); + const src = block.nodeOffset(pl_node.src_node); const bin = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; const ptr = try sema.resolveInst(bin.lhs); const operand = try sema.resolveInst(bin.rhs); @@ -5675,7 +5687,7 @@ fn storeToInferredAllocComptime( fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const quota: u32 = @intCast(try sema.resolveInt(block, src, inst_data.operand, Type.u32, .{ .needed_comptime_reason = "eval branch quota must be comptime-known", })); @@ -5690,7 +5702,7 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v const zir_tags = sema.code.instructions.items(.tag); const zir_datas = sema.code.instructions.items(.data); const inst_data = zir_datas[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const ptr = try sema.resolveInst(extra.lhs); const operand = try sema.resolveInst(extra.rhs); @@ -5824,7 +5836,7 @@ fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const msg = try sema.resolveConstString(block, operand_src, inst_data.operand, .{ .needed_comptime_reason = "compile error string must be comptime-known", @@ -5874,7 +5886,7 @@ fn zirCompileLog( fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const msg_inst = try sema.resolveInst(inst_data.operand); // `panicWithMsg` would perform this coercion for us, but we can get a better @@ -5901,7 +5913,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = parent_block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index); const body = sema.code.bodySlice(extra.end, extra.data.body_len); const gpa = sema.gpa; @@ -5974,7 +5986,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr const comp = mod.comp; const gpa = sema.gpa; const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = pl_node.src(); + const src = parent_block.nodeOffset(pl_node.src_node); const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index); const body = sema.code.bodySlice(extra.end, extra.data.body_len); @@ -6076,7 +6088,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr fn zirSuspendBlock(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 = inst_data.src(); + const src = parent_block.nodeOffset(inst_data.src_node); return sema.failWithUseOfAsync(parent_block, src); } @@ -6085,7 +6097,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt defer tracy.end(); const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = pl_node.src(); + const src = parent_block.nodeOffset(pl_node.src_node); const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index); const body = sema.code.bodySlice(extra.end, extra.data.body_len); const gpa = sema.gpa; @@ -6420,7 +6432,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const mod = sema.mod; 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 = inst_data.src(); + 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 decl_name = try mod.intern_pool.getOrPutString( @@ -6460,7 +6472,7 @@ fn zirExportValue(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 extra = sema.code.extraData(Zir.Inst.ExportValue, inst_data.payload_index).data; - const src = inst_data.src(); + 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 = try sema.resolveInstConst(block, operand_src, extra.operand, .{ @@ -6777,7 +6789,7 @@ fn addDbgVar( fn zirDeclRef(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)].str_tok; - const src = inst_data.src(); + const src = block.tokenOffset(inst_data.src_tok); const decl_name = try mod.intern_pool.getOrPutString( sema.gpa, inst_data.get(sema.code), @@ -6791,7 +6803,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air fn zirDeclVal(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)].str_tok; - const src = inst_data.src(); + const src = block.tokenOffset(inst_data.src_tok); const decl_name = try mod.intern_pool.getOrPutString( sema.gpa, inst_data.get(sema.code), @@ -7059,7 +7071,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 call_src = inst_data.src(); + const call_src = block.nodeOffset(inst_data.src_node); const ExtraType = switch (kind) { .direct => Zir.Inst.Call, .field => Zir.Inst.FieldCall, @@ -8084,7 +8096,7 @@ fn analyzeInlineCallArg( // Evaluate the parameter type expression now that previous ones have // been mapped, and coerce the corresponding argument to it. const pl_tok = ics.callee().code.instructions.items(.data)[@intFromEnum(inst)].pl_tok; - const param_src = pl_tok.src(); + const param_src = param_block.tokenOffset(pl_tok.src_tok); const extra = ics.callee().code.extraData(Zir.Inst.Param, pl_tok.payload_index); const param_body = ics.callee().code.bodySlice(extra.end, extra.data.body_len); const param_ty = param_ty: { @@ -8324,7 +8336,11 @@ fn instantiateGenericCall( } const param_ty_inst = try child_sema.resolveInlineBody(&child_block, param_ty_body, param_inst); - break :param_ty try child_sema.analyzeAsType(&child_block, param_data.src(), param_ty_inst); + break :param_ty try child_sema.analyzeAsType( + &child_block, + child_block.tokenOffset(param_data.src_tok), + param_ty_inst, + ); }, else => unreachable, } @@ -8358,11 +8374,11 @@ fn instantiateGenericCall( const arg_src = args_info.argSrc(block, arg_index); const msg = try sema.errMsg(block, arg_src, "runtime-known argument passed to comptime parameter", .{}); errdefer msg.destroy(sema.gpa); - const param_src = switch (param_tag) { - .param_comptime => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].pl_tok.src(), - .param_anytype_comptime => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].str_tok.src(), + 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", .{}); break :msg msg; }), @@ -8373,11 +8389,11 @@ fn instantiateGenericCall( 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", .{}); errdefer msg.destroy(sema.gpa); - const param_src = switch (param_tag) { - .param => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].pl_tok.src(), - .param_anytype => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].str_tok.src(), + 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); @@ -8560,7 +8576,7 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn zirIndexablePtrElemType(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 src = un_node.src(); + const src = block.nodeOffset(un_node.src_node); const ptr_ty = sema.resolveType(block, src, un_node.operand) catch |err| switch (err) { error.GenericPoison => return .generic_poison_type, else => |e| return e, @@ -8585,7 +8601,7 @@ fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr else => |e| return e, }; if (!vec_ty.isVector(mod)) { - return sema.fail(block, un_node.src(), "expected vector type, found '{}'", .{vec_ty.fmt(mod)}); + return sema.fail(block, block.nodeOffset(un_node.src_node), "expected vector type, found '{}'", .{vec_ty.fmt(mod)}); } return Air.internedToRef(vec_ty.childType(mod).toIntern()); } @@ -8672,7 +8688,7 @@ fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; if (true) { - return sema.failWithUseOfAsync(block, inst_data.src()); + 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 }; @@ -8888,7 +8904,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError fn zirIntFromEnum(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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); @@ -8946,7 +8962,7 @@ fn zirEnumFromInt(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 extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt"); const operand = try sema.resolveInst(extra.rhs); @@ -9015,7 +9031,7 @@ fn zirOptionalPayloadPtr( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const optional_ptr = try sema.resolveInst(inst_data.operand); - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false); } @@ -9099,7 +9115,7 @@ fn zirOptionalPayload( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const result_ty = switch (operand_ty.zigTypeTag(mod)) { @@ -9151,7 +9167,7 @@ fn zirErrUnionPayload( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); const operand_src = src; const err_union_ty = sema.typeOf(operand); @@ -9204,7 +9220,7 @@ fn zirErrUnionPayloadPtr( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = try sema.resolveInst(inst_data.operand); - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); return sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); } @@ -9288,7 +9304,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); return sema.analyzeErrUnionCode(block, src, operand); } @@ -9321,7 +9337,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); return sema.analyzeErrUnionCodePtr(block, src, operand); } @@ -9997,11 +10013,11 @@ fn finishFunc( param_body[0..block.params.len], ) |is_comptime, name_nts, param_index| { if (!is_comptime) { - const param_src = switch (tags[@intFromEnum(param_index)]) { - .param => data[@intFromEnum(param_index)].pl_tok.src(), - .param_anytype => data[@intFromEnum(param_index)].str_tok.src(), + const param_src = block.tokenOffset(switch (tags[@intFromEnum(param_index)]) { + .param => data[@intFromEnum(param_index)].pl_tok.src_tok, + .param_anytype => data[@intFromEnum(param_index)].str_tok.src_tok, else => unreachable, - }; + }); 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}); @@ -10084,7 +10100,7 @@ fn zirParam( comptime_syntax: bool, ) CompileError!void { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok; - const src = inst_data.src(); + const src = block.tokenOffset(inst_data.src_tok); const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); const param_name: Zir.NullTerminatedString = extra.data.name; const body = sema.code.bodySlice(extra.end, extra.data.body_len); @@ -10194,7 +10210,7 @@ fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.As, inst_data.payload_index).data; return sema.analyzeAs(block, src, extra.dest_type, extra.operand, false); } @@ -10204,7 +10220,7 @@ fn zirAsShiftOperand(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.As, inst_data.payload_index).data; return sema.analyzeAs(block, src, extra.dest_type, extra.operand, true); } @@ -10301,7 +10317,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! .storage = .{ .elems = new_elems }, } })); } - try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); + try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src); try sema.validateRuntimeValue(block, ptr_src, operand); if (!is_vector) { return block.addUnOp(.int_from_ptr, operand); @@ -10323,7 +10339,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const field_name_src: LazySrcLoc = .{ .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( @@ -10341,7 +10357,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const field_name_src: LazySrcLoc = .{ .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( @@ -10359,7 +10375,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const field_name_src: LazySrcLoc = .{ .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( @@ -10384,7 +10400,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; const object = try sema.resolveInst(extra.lhs); @@ -10399,7 +10415,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; const object_ptr = try sema.resolveInst(extra.lhs); @@ -10414,14 +10430,14 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; 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"); const operand = try sema.resolveInst(extra.rhs); - return sema.intCast(block, inst_data.src(), dest_ty, src, operand, operand_src, true); + return sema.intCast(block, block.nodeOffset(inst_data.src_node), dest_ty, src, operand, operand_src, true); } fn intCast( @@ -10584,7 +10600,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; @@ -10718,7 +10734,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .Vector, => {}, } - return sema.bitCast(block, dest_ty, operand, inst_data.src(), operand_src); + return sema.bitCast(block, dest_ty, operand, block.nodeOffset(inst_data.src_node), operand_src); } fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -10727,7 +10743,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; @@ -10781,7 +10797,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A if (dest_is_comptime_float) { return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_float'", .{}); } - try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); + try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), operand_src); const src_bits = operand_scalar_ty.floatBits(target); const dst_bits = dest_scalar_ty.floatBits(target); @@ -10806,7 +10822,7 @@ fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(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 elem_index = try sema.resolveInst(extra.rhs); @@ -10818,7 +10834,7 @@ fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const elem_index_src: LazySrcLoc = .{ .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); @@ -10844,7 +10860,7 @@ fn zirElemPtr(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 = inst_data.src(); + const src = block.nodeOffset(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 elem_index = try sema.resolveInst(extra.rhs); @@ -10871,7 +10887,7 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const elem_index_src: LazySrcLoc = .{ .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); @@ -10886,7 +10902,7 @@ fn zirArrayInitElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data; const array_ptr = try sema.resolveInst(extra.ptr); const elem_index = try sema.mod.intRef(Type.usize, extra.index); @@ -10905,7 +10921,7 @@ fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); 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); @@ -10921,7 +10937,7 @@ fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data; const array_ptr = try sema.resolveInst(extra.lhs); const start = try sema.resolveInst(extra.start); @@ -10938,7 +10954,7 @@ fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const sentinel_src: LazySrcLoc = .{ .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); @@ -10957,7 +10973,7 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data; const array_ptr = try sema.resolveInst(extra.lhs); const start = try sema.resolveInst(extra.start); @@ -11017,7 +11033,9 @@ const SwitchProngAnalysis = struct { merges: *Block.Merges, ) CompileError!Air.Inst.Ref { const sema = spa.sema; - const src = sema.code.instructions.items(.data)[@intFromEnum(spa.switch_block_inst)].pl_node.src(); + const src = spa.parent_block.nodeOffset( + sema.code.instructions.items(.data)[@intFromEnum(spa.switch_block_inst)].pl_node.src_node, + ); if (has_tag_capture) { const tag_ref = try spa.analyzeTagCapture(child_block, raw_capture_src, inline_case_capture); @@ -11566,7 +11584,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const mod = sema.mod; const gpa = sema.gpa; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const switch_src = inst_data.src(); + 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 }; @@ -11874,7 +11892,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r const mod = sema.mod; const gpa = sema.gpa; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + 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 }; @@ -13396,7 +13414,7 @@ fn validateErrSetSwitch( const ip = &mod.intern_pool; const src_node_offset = inst_data.src_node; - const src = inst_data.src(); + const src = block.nodeOffset(src_node_offset); var extra_index: usize = else_case.end; { @@ -13836,7 +13854,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I } } else return; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable"; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); if (try sema.resolveDefinedValue(block, src, operand)) |val| { if (val.getErrorName(sema.mod).unwrap()) |name| { @@ -13900,7 +13918,7 @@ fn zirHasDecl(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.Bin, inst_data.payload_index).data; - const src = inst_data.src(); + 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 container_type = try sema.resolveType(block, lhs_src, extra.lhs); @@ -13932,7 +13950,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; - const operand_src = inst_data.src(); + const operand_src = block.tokenOffset(inst_data.src_tok); const operand = inst_data.get(sema.code); const result = mod.importFile(block.getFileScope(mod), operand) catch |err| switch (err) { @@ -14012,7 +14030,7 @@ fn zirShl( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + 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 extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; @@ -14182,7 +14200,7 @@ fn zirShr( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + 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 extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; @@ -14371,7 +14389,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; const operand = try sema.resolveInst(inst_data.operand); @@ -14520,7 +14538,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const rhs = try sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const lhs_is_tuple = lhs_ty.isTuple(mod); const rhs_is_tuple = rhs_ty.isTuple(mod); @@ -14871,7 +14889,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const extra = sema.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data; const uncoerced_lhs = try sema.resolveInst(extra.lhs); const uncoerced_lhs_ty = sema.typeOf(uncoerced_lhs); - const src: LazySrcLoc = inst_data.src(); + 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 }; @@ -15041,7 +15059,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn zirNegate(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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const lhs_src = src; const rhs_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; @@ -15073,7 +15091,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. fn zirNegateWrap(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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const lhs_src = src; const rhs_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; @@ -16991,7 +17009,7 @@ fn zirLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.In defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ptr_src = src; // TODO better source location const ptr = try sema.resolveInst(inst_data.operand); return sema.analyzeLoad(block, src, ptr, ptr_src); @@ -17181,7 +17199,7 @@ fn zirCmpEq( 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 src: LazySrcLoc = inst_data.src(); + 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 = try sema.resolveInst(extra.lhs); @@ -17297,7 +17315,7 @@ 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 = inst_data.src(); + 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 = try sema.resolveInst(extra.lhs); @@ -17724,7 +17742,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const gpa = sema.gpa; const ip = &mod.intern_pool; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ty = try sema.resolveType(block, src, inst_data.operand); const type_info_ty = try sema.getBuiltinType("Type"); const type_info_tag_ty = type_info_ty.unionTagType(mod).?; @@ -18906,7 +18924,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr fn zirTypeofLog2IntType(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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const res_ty = try sema.log2IntType(block, operand_ty, src); @@ -18998,7 +19016,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; const uncasted_operand = try sema.resolveInst(inst_data.operand); @@ -19155,7 +19173,7 @@ fn zirIsNonNull( defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); try sema.checkNullableType(block, src, sema.typeOf(operand)); return sema.analyzeIsNull(block, src, operand, true); @@ -19171,7 +19189,7 @@ fn zirIsNonNullPtr( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ptr = try sema.resolveInst(inst_data.operand); try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2(mod)); if ((try sema.resolveValue(ptr)) == null) { @@ -19196,7 +19214,7 @@ fn zirIsNonErr(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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); try sema.checkErrorType(block, src, sema.typeOf(operand)); return sema.analyzeIsNonErr(block, src, operand); @@ -19208,7 +19226,7 @@ fn zirIsNonErrPtr(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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ptr = try sema.resolveInst(inst_data.operand); try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2(mod)); const loaded = try sema.analyzeLoad(block, src, ptr, src); @@ -19220,7 +19238,7 @@ fn zirRetIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); return sema.analyzeIsNonErr(block, src, operand); } @@ -19302,7 +19320,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 = inst_data.src(); + const src = parent_block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .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); @@ -19349,7 +19367,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 = inst_data.src(); + const src = parent_block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .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); @@ -19474,7 +19492,7 @@ fn addRuntimeBreak(sema: *Sema, child_block: *Block, block_inst: Zir.Inst.Index, fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable"; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); if (block.is_comptime) { return sema.fail(block, src, "reached unreachable code", .{}); @@ -19498,13 +19516,13 @@ fn zirRetErrValue( ) CompileError!void { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; + const src = block.tokenOffset(inst_data.src_tok); const err_name = try mod.intern_pool.getOrPutString( sema.gpa, inst_data.get(sema.code), .no_embedded_nulls, ); _ = try mod.getErrorValue(err_name); - const src = inst_data.src(); // Return the error code from the function. const error_set_type = try mod.singleErrorSetType(err_name); const result_inst = Air.internedToRef((try mod.intern(.{ .err = .{ @@ -19524,7 +19542,7 @@ fn zirRetImplicit( const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; - const r_brace_src = inst_data.src(); + const r_brace_src = block.tokenOffset(inst_data.src_tok); if (block.inlining == null and sema.func_is_naked) { assert(!block.is_comptime); if (block.wantSafety()) { @@ -19570,7 +19588,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = try sema.resolveInst(inst_data.operand); - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node }); } @@ -19580,7 +19598,7 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ret_ptr = try sema.resolveInst(inst_data.operand); if (block.is_comptime or block.inlining != null or sema.func_is_naked) { @@ -19679,7 +19697,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { const extra = sema.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data; - return sema.restoreErrRetIndex(start_block, extra.src(), extra.block, extra.operand); + return sema.restoreErrRetIndex(start_block, start_block.nodeOffset(extra.src_node), extra.block, extra.operand); } /// If `operand` is non-error (or is `none`), restores the error return trace to @@ -20006,7 +20024,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node }; const obj_ty = try sema.resolveType(block, ty_src, inst_data.operand); const mod = sema.mod; @@ -20026,7 +20044,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const ty_operand = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) { // Generic poison means this is an untyped anonymous empty struct init error.GenericPoison => return .empty_struct, @@ -20158,7 +20176,7 @@ fn zirStructInit( const zir_datas = sema.code.instructions.items(.data); const inst_data = zir_datas[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const mod = sema.mod; const ip = &mod.intern_pool; @@ -20503,7 +20521,7 @@ fn zirStructInitAnon( inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index); return sema.structInitAnon(block, src, .anon_init, extra.data, extra.end, false); } @@ -20655,7 +20673,7 @@ fn zirArrayInit( const mod = sema.mod; const gpa = sema.gpa; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); const args = sema.code.refSlice(extra.end, extra.data.operands_len); @@ -20818,7 +20836,7 @@ fn zirArrayInitAnon( inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); const operands = sema.code.refSlice(extra.end, extra.data.operands_len); return sema.arrayInitAnon(block, src, operands, false); @@ -20931,7 +20949,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const ip = &mod.intern_pool; 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 = inst_data.src(); + const ty_src = block.nodeOffset(inst_data.src_node); const field_name_src: LazySrcLoc = .{ .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 @@ -21054,7 +21072,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air fn zirIntFromBool(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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const is_vector = operand_ty.zigTypeTag(mod) == .Vector; @@ -21216,7 +21234,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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const mod = sema.mod; @@ -22512,20 +22530,20 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn zirFrameType(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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); return sema.failWithUseOfAsync(block, src); } fn zirFrameSize(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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); return sema.failWithUseOfAsync(block, src); } fn zirIntFromFloat(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 = inst_data.src(); + 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 dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat"); @@ -22550,7 +22568,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro }); } - try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); + try sema.requireRuntimeBlock(block, src, operand_src); if (dest_scalar_ty.intInfo(mod).bits == 0) { if (!is_vector) { if (block.wantSafety()) { @@ -22607,7 +22625,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro fn zirFloatFromInt(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 = inst_data.src(); + 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 dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt"); @@ -22649,7 +22667,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro fn zirPtrFromInt(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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; @@ -22934,7 +22952,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; 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"); @@ -23381,7 +23399,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst fn zirTruncate(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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; 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"); @@ -23471,7 +23489,7 @@ fn zirBitCount( ) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); @@ -23525,7 +23543,7 @@ fn zirBitCount( fn zirByteSwap(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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); @@ -23581,7 +23599,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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand = try sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); @@ -24290,7 +24308,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I 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 src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); const scalar_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@splat"); @@ -24312,7 +24330,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I return Air.internedToRef((try sema.splat(dest_ty, scalar_val)).toIntern()); } - try sema.requireRuntimeBlock(block, inst_data.src(), scalar_src); + try sema.requireRuntimeBlock(block, src, scalar_src); return block.addTyOp(.splat, dest_ty, scalar); } @@ -24377,7 +24395,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. return Air.internedToRef(accum.toIntern()); } - try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); + try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), operand_src); return block.addInst(.{ .tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce, .data = .{ .reduce = .{ @@ -24704,7 +24722,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } } - try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); + try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src); return block.addInst(.{ .tag = .atomic_load, .data = .{ .atomic_load = .{ @@ -24718,7 +24736,7 @@ fn zirAtomicRmw(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 extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data; - const src = inst_data.src(); + 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 }; @@ -24803,7 +24821,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A fn zirAtomicStore(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.AtomicStore, inst_data.payload_index).data; - const src = inst_data.src(); + 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 }; @@ -24839,7 +24857,7 @@ fn zirAtomicStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError fn zirMulAdd(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.MulAdd, inst_data.payload_index).data; - const src = inst_data.src(); + 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 }; @@ -24909,7 +24927,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError 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 call_src = inst_data.src(); + const call_src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data; const func = try sema.resolveInst(extra.callee); @@ -25003,7 +25021,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); assert(!flags.ptr_cast); - const inst_src = extra.src(); + 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 }; @@ -25213,7 +25231,7 @@ fn zirMinMax( ) 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 src = inst_data.src(); + 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 = try sema.resolveInst(extra.lhs); @@ -25514,7 +25532,7 @@ fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !A 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 = inst_data.src(); + 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_ptr = try sema.resolveInst(extra.lhs); @@ -25734,7 +25752,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void 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 = inst_data.src(); + 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_ptr = try sema.resolveInst(extra.lhs); @@ -25819,7 +25837,7 @@ fn zirBuiltinAsyncCall(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.I fn zirResume(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 = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); return sema.failWithUseOfAsync(block, src); } @@ -25829,7 +25847,7 @@ fn zirAwait( inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const src = inst_data.src(); + const src = block.nodeOffset(inst_data.src_node); return sema.failWithUseOfAsync(block, src); } diff --git a/src/Sema/comptime_ptr_access.zig b/src/Sema/comptime_ptr_access.zig index c1fb54456132..1eddc8d7a6d8 100644 --- a/src/Sema/comptime_ptr_access.zig +++ b/src/Sema/comptime_ptr_access.zig @@ -1048,7 +1048,6 @@ fn checkComptimeVarStore( const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; -const LazySrcLoc = std.zig.LazySrcLoc; const InternPool = @import("../InternPool.zig"); const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; @@ -1057,3 +1056,5 @@ const Block = Sema.Block; const MutableValue = @import("../mutable_value.zig").MutableValue; const Type = @import("../type.zig").Type; const Value = @import("../Value.zig"); +const Zcu = @import("../Module.zig"); +const LazySrcLoc = Zcu.LazySrcLoc; diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index fe94c061365f..023c023430dd 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -16,7 +16,7 @@ const Decl = Module.Decl; const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); const Compilation = @import("../../Compilation.zig"); -const LazySrcLoc = std.zig.LazySrcLoc; +const LazySrcLoc = Module.LazySrcLoc; const link = @import("../../link.zig"); const Air = @import("../../Air.zig"); const Liveness = @import("../../Liveness.zig"); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 9514b826eaa8..52290b5ee4c9 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -13,7 +13,7 @@ const Type = @import("../type.zig").Type; const C = link.File.C; const Decl = Zcu.Decl; const trace = @import("../tracy.zig").trace; -const LazySrcLoc = std.zig.LazySrcLoc; +const LazySrcLoc = Zcu.LazySrcLoc; const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const InternPool = @import("../InternPool.zig"); diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index d38cd5d40087..3a0e3b42f84b 100644 --- a/src/codegen/c/Type.zig +++ b/src/codegen/c/Type.zig @@ -2581,8 +2581,8 @@ pub const AlignAs = packed struct { const Alignment = @import("../../InternPool.zig").Alignment; const assert = std.debug.assert; const CType = @This(); -const DeclIndex = std.zig.DeclIndex; const Module = @import("../../Package/Module.zig"); const std = @import("std"); const Type = @import("../../type.zig").Type; const Zcu = @import("../../Module.zig"); +const DeclIndex = @import("../../InternPool.zig").DeclIndex; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2f2625948c66..53ece2c5711b 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -22,7 +22,7 @@ const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const Value = @import("../Value.zig"); const Type = @import("../type.zig").Type; -const LazySrcLoc = std.zig.LazySrcLoc; +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"); diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 09185211ef59..aec87b287ae4 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -9,7 +9,7 @@ const Module = @import("../Module.zig"); const Decl = Module.Decl; const Type = @import("../type.zig").Type; const Value = @import("../Value.zig"); -const LazySrcLoc = std.zig.LazySrcLoc; +const LazySrcLoc = Module.LazySrcLoc; const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const InternPool = @import("../InternPool.zig"); diff --git a/src/print_zir.zig b/src/print_zir.zig index d5772949eb95..0150a7bacc1c 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -6,8 +6,9 @@ const Ast = std.zig.Ast; const InternPool = @import("InternPool.zig"); const Zir = std.zig.Zir; -const Module = @import("Module.zig"); -const LazySrcLoc = std.zig.LazySrcLoc; +const Zcu = @import("Module.zig"); +const Module = Zcu; +const LazySrcLoc = Zcu.LazySrcLoc; /// Write human-readable, debug formatted ZIR code to a file. pub fn renderAsTextToFile( @@ -630,7 +631,7 @@ const Writer = struct { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_node; try self.writeInstRef(stream, inst_data.operand); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeUnTok( @@ -641,7 +642,7 @@ const Writer = struct { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; try self.writeInstRef(stream, inst_data.operand); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcTok(stream, inst_data.src_tok); } fn writeValidateDestructure( @@ -655,7 +656,7 @@ const Writer = struct { try stream.print(", {d}) (destructure=", .{extra.expect_len}); try self.writeSrc(stream, LazySrcLoc.nodeOffset(extra.destructure_node)); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeValidateArrayInitTy( @@ -667,7 +668,7 @@ const Writer = struct { const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; try self.writeInstRef(stream, extra.ty); try stream.print(", {d}) ", .{extra.init_count}); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeArrayTypeSentinel( @@ -683,7 +684,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.elem_type); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writePtrType( @@ -763,11 +764,10 @@ const Writer = struct { fn writeFloat128(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data; - const src = inst_data.src(); const number = extra.get(); // TODO improve std.format to be able to print f128 values try stream.print("{d}) ", .{@as(f64, @floatCast(number))}); - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeStr( @@ -787,7 +787,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.start); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeSliceEnd(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -799,7 +799,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.end); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeSliceSentinel(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -813,7 +813,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.sentinel); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeSliceLength(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -829,7 +829,7 @@ const Writer = struct { try self.writeInstRef(stream, extra.sentinel); } try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeUnionInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -841,7 +841,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.init); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeShuffle(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -855,7 +855,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.mask); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeSelect(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { @@ -880,7 +880,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.addend); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeBuiltinCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -896,7 +896,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.args); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeFieldParentPtr(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { @@ -913,7 +913,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.field_ptr); try stream.writeAll(") "); - try self.writeSrc(stream, extra.src()); + try self.writeSrcNode(stream, extra.src_node); } fn writeBuiltinAsyncCall(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { @@ -944,7 +944,7 @@ const Writer = struct { } try self.writeBracedBody(stream, body); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcTok(stream, inst_data.src_tok); } fn writePlNodeBin(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -954,7 +954,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.rhs); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writePlNodeMultiOp(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -967,7 +967,7 @@ const Writer = struct { try self.writeInstRef(stream, arg); } try stream.writeAll("}) "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeArrayMul(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -979,7 +979,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.rhs); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeElemValImm(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -994,7 +994,7 @@ const Writer = struct { try self.writeInstRef(stream, extra.ptr); try stream.print(", {d}) ", .{extra.index}); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writePlNodeExport(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1006,7 +1006,7 @@ const Writer = struct { try stream.print(", {p}, ", .{std.zig.fmtId(decl_name)}); try self.writeInstRef(stream, extra.options); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writePlNodeExportValue(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1017,7 +1017,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.options); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeValidateArrayInitRefTy(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1027,7 +1027,7 @@ const Writer = struct { try self.writeInstRef(stream, extra.ptr_ty); try stream.writeAll(", "); try stream.print(", {}) ", .{extra.elem_count}); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeStructInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1051,7 +1051,7 @@ const Writer = struct { try stream.writeAll("]"); } try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeCmpxchg(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { @@ -1110,7 +1110,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.ordering); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeAtomicStore(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1123,7 +1123,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.ordering); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeAtomicRmw(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1138,7 +1138,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.ordering); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeStructInitAnon(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1159,7 +1159,7 @@ const Writer = struct { try stream.writeAll("]"); } try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeStructInitFieldType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1168,7 +1168,7 @@ const Writer = struct { try self.writeInstRef(stream, extra.container_type); const field_name = self.code.nullTerminatedString(extra.name_start); try stream.print(", {s}) ", .{field_name}); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeFieldTypeRef(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1178,7 +1178,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.field_name); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { @@ -1202,7 +1202,7 @@ const Writer = struct { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].inst_node; try self.writeInstIndex(stream, inst_data.inst); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeAsm( @@ -1347,13 +1347,13 @@ const Writer = struct { } try stream.writeAll("]) "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; try self.writePlNodeBlockWithoutSrc(stream, inst); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writePlNodeBlockWithoutSrc(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1375,7 +1375,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeBracedBody(stream, else_body); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeTry(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -1386,7 +1386,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeBracedBody(stream, body); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeStructDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { @@ -1480,7 +1480,7 @@ const Writer = struct { } if (fields_len == 0) { - try stream.writeAll("{}, {})"); + try stream.writeAll("{}, {}) "); } else { const bits_per_field = 4; const fields_per_u32 = 32 / bits_per_field; @@ -1596,7 +1596,7 @@ const Writer = struct { self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); - try stream.writeAll("})"); + try stream.writeAll("}) "); } try self.writeSrcNode(stream, 0); } @@ -1688,7 +1688,7 @@ const Writer = struct { } if (fields_len == 0) { - try stream.writeAll("})"); + try stream.writeAll("}) "); try self.writeSrcNode(stream, 0); return; } @@ -1762,7 +1762,7 @@ const Writer = struct { self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); - try stream.writeAll("})"); + try stream.writeAll("}) "); try self.writeSrcNode(stream, 0); } @@ -1855,7 +1855,7 @@ const Writer = struct { try self.writeBracedDecl(stream, body); if (fields_len == 0) { - try stream.writeAll(", {})"); + try stream.writeAll(", {}) "); } else { try stream.writeAll(", {\n"); @@ -1896,7 +1896,7 @@ const Writer = struct { } self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); - try stream.writeAll("})"); + try stream.writeAll("}) "); } try self.writeSrcNode(stream, 0); } @@ -1944,14 +1944,14 @@ const Writer = struct { } if (decls_len == 0) { - try stream.writeAll("{})"); + try stream.writeAll("{}) "); } else { try stream.writeAll("{\n"); self.indent += 2; try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); - try stream.writeAll("})"); + try stream.writeAll("}) "); } try self.writeSrcNode(stream, 0); } @@ -1982,7 +1982,7 @@ const Writer = struct { try stream.writeByteNTimes(' ', self.indent); try stream.writeAll("}) "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeSwitchBlockErrUnion(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2119,7 +2119,7 @@ const Writer = struct { self.indent -= 2; try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeSwitchBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2249,7 +2249,7 @@ const Writer = struct { self.indent -= 2; try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writePlNodeField(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2258,7 +2258,7 @@ const Writer = struct { const name = self.code.nullTerminatedString(extra.field_name_start); try self.writeInstRef(stream, extra.lhs); try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)}); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writePlNodeFieldNamed(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2268,7 +2268,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.field_name); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeAs(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2278,7 +2278,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeInstRef(stream, extra.operand); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeNode( @@ -2300,7 +2300,7 @@ const Writer = struct { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const str = inst_data.get(self.code); try stream.print("\"{}\") ", .{std.zig.fmtEscapes(str)}); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcTok(stream, inst_data.src_tok); } fn writeStrOp(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2317,7 +2317,6 @@ const Writer = struct { inferred_error_set: bool, ) !void { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; - const src = inst_data.src(); const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index); var extra_index = extra.end; @@ -2364,7 +2363,7 @@ const Writer = struct { ret_ty_body, body, - src, + inst_data.src_node, src_locs, 0, ); @@ -2373,7 +2372,6 @@ const Writer = struct { fn writeFuncFancy(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); - const src = inst_data.src(); var extra_index: usize = extra.end; var align_ref: Zir.Inst.Ref = .none; @@ -2470,7 +2468,7 @@ const Writer = struct { ret_ty_ref, ret_ty_body, body, - src, + inst_data.src_node, src_locs, noalias_bits, ); @@ -2551,7 +2549,7 @@ const Writer = struct { try stream.writeAll(", "); try self.writeBracedBody(stream, body); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeIntType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2561,7 +2559,7 @@ const Writer = struct { .unsigned => 'u', }; try stream.print("{c}{d}) ", .{ prefix, int_type.bit_count }); - try self.writeSrc(stream, int_type.src()); + try self.writeSrcNode(stream, int_type.src_node); } fn writeSaveErrRetIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2579,7 +2577,7 @@ const Writer = struct { try self.writeInstRef(stream, extra.operand); try stream.writeAll(") "); - try self.writeSrc(stream, extra.src()); + try self.writeSrcNode(stream, extra.src_node); } fn writeBreak(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2605,7 +2603,7 @@ const Writer = struct { try self.writeInstRef(stream, arg); } try stream.writeAll("}) "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeArrayInitAnon(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2620,7 +2618,7 @@ const Writer = struct { try self.writeInstRef(stream, arg); } try stream.writeAll("}) "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeArrayInitSent(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2640,13 +2638,13 @@ const Writer = struct { try self.writeInstRef(stream, elem); } try stream.writeAll("}) "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeUnreachable(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable"; try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrcNode(stream, inst_data.src_node); } fn writeFuncCommon( @@ -2667,7 +2665,7 @@ const Writer = struct { ret_ty_ref: Zir.Inst.Ref, ret_ty_body: []const Zir.Inst.Index, body: []const Zir.Inst.Index, - src: LazySrcLoc, + src_node: i32, src_locs: Zir.Inst.Func.SrcLocs, noalias_bits: u32, ) !void { @@ -2694,7 +2692,7 @@ const Writer = struct { src_locs.rbrace_line + 1, @as(u16, @truncate(src_locs.columns >> 16)) + 1, }); } - try self.writeSrc(stream, src); + try self.writeSrcNode(stream, src_node); } fn writeDbgStmt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { @@ -2878,11 +2876,12 @@ const Writer = struct { } } - fn writeSrcNode(self: *Writer, stream: anytype, src_node: ?i32) !void { - const node_offset = src_node orelse return; - const src = LazySrcLoc.nodeOffset(node_offset); - try stream.writeAll(" "); - return self.writeSrc(stream, src); + fn writeSrcNode(self: *Writer, stream: anytype, src_node: i32) !void { + return self.writeSrc(stream, LazySrcLoc.nodeOffset(src_node)); + } + + fn writeSrcTok(self: *Writer, stream: anytype, src_tok: u32) !void { + return self.writeSrc(stream, .{ .token_offset = src_tok }); } fn writeBracedDecl(self: *Writer, stream: anytype, body: []const Zir.Inst.Index) !void { From 1eaeb4a0a838a783d2060f4e5b3b26b483b26009 Mon Sep 17 00:00:00 2001 From: mlugg Date: Fri, 14 Jun 2024 23:05:39 +0100 Subject: [PATCH 03/10] Zcu: rework source locations `LazySrcLoc` now stores a reference to the "base AST node" to which it is relative. The previous tagged union is `LazySrcLoc.Offset`. To make working with this structure convenient, `Sema.Block` contains a convenience `src` method which takes an `Offset` and returns a `LazySrcLoc`. The "base node" of a source location is no longer given by a `Decl`, but rather a `TrackedInst` representing either a `declaration`, `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl`. This is a more appropriate model, and removes an unnecessary responsibility from `Decl` in preparation for the upcoming refactor which will split it into `Nav` and `Cau`. As a part of these `Decl` reworks, the `src_node` field is eliminated. This change aids incremental compilation, and simplifies `Decl`. In some cases -- particularly in backends -- the source location of a declaration is desired. This was previously `Decl.srcLoc` and worked for any `Decl`. Now, it is `Decl.navSrcLoc` in reference to the upcoming refactor, since the set of `Decl`s this works for precisely corresponds to what will in future become a `Nav` -- that is, source-level declarations and generic function instantiations, but *not* type owner Decls. This commit introduces more tags to `LazySrcLoc.Offset` so as to eliminate the concept of `error.NeededSourceLocation`. Now, `.unneeded` should only be used to assert that an error path is unreachable. In the future, uses of `.unneeded` can probably be replaced with `undefined`. The `src_decl` field of `Sema.Block` no longer has a role in type resolution. Its main remaining purpose is to handle namespacing of type names. It will be eliminated entirely in a future commit to remove another undue responsibility from `Decl`. It is worth noting that in future, the `Zcu.SrcLoc` type should probably be eliminated entirely in favour of storing `Zcu.LazySrcLoc` values. This is because `Zcu.SrcLoc` is not valid across incremental updates, and we want to be able to reuse error messages from previous updates even if the source file in question changed. The error reporting logic should instead simply resolve the location from the `LazySrcLoc` on the fly. --- src/Compilation.zig | 37 +- src/InternPool.zig | 6 +- src/Module.zig | 1805 ++++------ src/RangeSet.zig | 8 +- src/Sema.zig | 3166 ++++++++--------- src/Sema/comptime_ptr_access.zig | 8 +- src/Value.zig | 1 - src/arch/wasm/CodeGen.zig | 5 +- src/arch/wasm/Emit.zig | 2 +- src/codegen/c.zig | 3 +- src/codegen/llvm.zig | 7 +- src/codegen/spirv.zig | 5 +- src/crash_report.zig | 23 +- src/link/Coff.zig | 12 +- src/link/Elf/ZigObject.zig | 16 +- src/link/MachO/ZigObject.zig | 12 +- src/link/Plan9.zig | 14 +- src/link/Wasm/ZigObject.zig | 10 +- src/print_value.zig | 2 +- src/print_zir.zig | 103 +- src/type.zig | 40 +- ...omptime_arg_to_generic_fn_callee_error.zig | 1 - .../enum_value_already_taken.zig | 2 +- ...xport_function_with_comptime_parameter.zig | 2 +- .../export_generic_function.zig | 2 +- ...xtern_function_with_comptime_parameter.zig | 2 +- ...ssing_field_in_struct_value_expression.zig | 4 +- ..._struct_field_in_fn_called_at_comptime.zig | 2 +- ...for_tagged_union_with_extra_enum_field.zig | 2 - ...or_tagged_union_with_extra_union_field.zig | 1 - ...e_for_tagged_union_with_no_enum_fields.zig | 1 - ..._for_tagged_union_with_no_union_fields.zig | 3 - .../switch_ranges_endpoints_are_validated.zig | 4 +- .../union_auto-enum_value_already_taken.zig | 4 +- 34 files changed, 2447 insertions(+), 2868 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 507cbfc6d55a..32243daf69c2 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 f1c90311c431..3669ab59d18f 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 283a4f75cc48..f857d0997b9a 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); + + 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; + }, + .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, + }; - 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, + 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; + }, + } }, - .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + arg_index], - else => unreachable, - }; - return tree.nodeToSpan(param); + } } }; -/// 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, - - 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 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, + + 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 nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; + 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, + }; - noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc { - var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; - result.node_offset.trace.addAddr(@returnAddress(), "init"); - return result; - } + 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, + }; - fn nodeOffsetRelease(node_offset: i32) LazySrcLoc { - return .{ .node_offset = .{ .x = node_offset } }; - } + pub const SwitchCaseIndex = packed struct(u32) { + kind: enum(u1) { scalar, multi }, + index: u31, - /// 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, + 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; + } - const want_tracing = false; + 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 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 00dc257d1a7c..4e2eaa633aa1 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 eacc4e097dc3..aa4d459f1bc7 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); - - 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; + 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, 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); - - 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; + 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, 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 1eddc8d7a6d8..de0afc4b85a4 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 99817d79a971..0eb036498667 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 023c023430dd..fa3ca6a28362 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 ded960daf198..957100ee3471 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 52290b5ee4c9..b3a381b278b7 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 53ece2c5711b..aaa33d4bebf8 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 aec87b287ae4..acfdf2b4f842 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 311647f23ff7..ed45c32681ac 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 d24d69d913bd..4a58e970c100 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 b27601b420ee..442f5797219c 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 6168d40d96c5..cf92503f5a57 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 ec5278e62b5d..ac6ae6752c98 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 dc49fffaa36c..7d9e7e1310f3 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 06ac9f4cd16c..e1a63e5b6aa4 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 0150a7bacc1c..e2d2f6e5000b 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 5dad904ca060..546234db378e 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 efc3f556a943..8d8516eecc8d 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 e3a13785e1dd..efb9e209cf07 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 948053534dba..8d5dbef1c36c 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 65469be6d942..4ffbad9df7d9 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 b8f5f0b1b826..fac09cc26519 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 d0b09643b84a..3b09df106f05 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 1f3c4583cb24..aaded91209c2 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 0ea0b019b9c4..25b58e7c29cd 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 ed6f2245d4b2..dd324f751cb1 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 91c5354c0cb1..188b4d9d6a66 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 2dc983247062..5c367e9ba656 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 b32e707ebde6..fd4cd5336495 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 31a027b7c023..d251b38c5499 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 From b8d2323b88e68bb5af061dd7e488f51aa0ae8176 Mon Sep 17 00:00:00 2001 From: mlugg Date: Sat, 15 Jun 2024 00:52:26 +0100 Subject: [PATCH 04/10] Sema: eliminate Block.src_decl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🦀 src_decl is gone 🦀 This commit eliminates the `src_decl` field from `Sema.Block`. This change goes further to eliminating unnecessary responsibilities of `Decl` in preparation for its major upcoming refactor. The two main remaining reponsibilities had to do with namespace types: `src_decl` was used to determine their line number and their name. The former use case is solved by storing the line number alongside type declarations (and reifications) in ZIR; this is actually more correct, since previously the line number assigned to the type was really the line number of the source declaration it was syntactically contained within, which does not necessarily line up. Consequently, this change makes debug info for namespace types more correct, although I am not sure how debuggers actually utilize this line number, if at all. Naming types was solved by a new field on `Block`, called `type_name_ctx`. In a sense, it represents the "namespace" we are currently within, including comptime function calls etc. We might want to revisit this in future, since the type naming rules seem to be a bit hand-wavey right now. As far as I can tell, there isn't any more preliminary work needed for me to start work on the behemoth task of splitting `Zcu.Decl` into the new `Nav` (Named Addressable Value) and `Cau` (Comptime Analysis Unit) types. This will be a sweeping change, impacting essentially every part of the pipeline after `AstGen`. --- lib/std/zig/AstGen.zig | 8 ++- lib/std/zig/Zir.zig | 12 +++- src/Module.zig | 80 +++++++++++++++---------- src/Sema.zig | 133 ++++++++++++++++++++++------------------- src/crash_report.zig | 11 +--- src/main.zig | 3 + src/print_zir.zig | 9 ++- 7 files changed, 154 insertions(+), 102 deletions(-) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index b356789bfda8..40fcf562798c 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -13132,6 +13132,7 @@ const GenZir = struct { .fields_hash_1 = fields_hash_arr[1], .fields_hash_2 = fields_hash_arr[2], .fields_hash_3 = fields_hash_arr[3], + .src_line = astgen.source_line, .src_node = args.src_node, }); @@ -13192,6 +13193,7 @@ const GenZir = struct { .fields_hash_1 = fields_hash_arr[1], .fields_hash_2 = fields_hash_arr[2], .fields_hash_3 = fields_hash_arr[3], + .src_line = astgen.source_line, .src_node = args.src_node, }); @@ -13253,6 +13255,7 @@ const GenZir = struct { .fields_hash_1 = fields_hash_arr[1], .fields_hash_2 = fields_hash_arr[2], .fields_hash_3 = fields_hash_arr[3], + .src_line = astgen.source_line, .src_node = args.src_node, }); @@ -13300,7 +13303,10 @@ const GenZir = struct { assert(args.src_node != 0); try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 2); - const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ .src_node = args.src_node }); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ + .src_line = astgen.source_line, + .src_node = args.src_node, + }); if (args.captures_len != 0) { astgen.extra.appendAssumeCapacity(args.captures_len); diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index beead16e3761..69fc2b9b76fd 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -1981,7 +1981,7 @@ pub const Inst = struct { /// `operand` is payload index to `UnNode`. error_from_int, /// Implement builtin `@Type`. - /// `operand` is payload index to `UnNode`. + /// `operand` is payload index to `Reify`. /// `small` contains `NameStrategy`. reify, /// Implements the `@asyncCall` builtin. @@ -2834,6 +2834,12 @@ pub const Inst = struct { index: u32, }; + pub const Reify = struct { + node: i32, + operand: Ref, + src_line: u32, + }; + pub const SwitchBlockErrUnion = struct { operand: Ref, bits: Bits, @@ -2992,6 +2998,7 @@ pub const Inst = struct { fields_hash_1: u32, fields_hash_2: u32, fields_hash_3: u32, + src_line: u32, /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, @@ -3121,6 +3128,7 @@ pub const Inst = struct { fields_hash_1: u32, fields_hash_2: u32, fields_hash_3: u32, + src_line: u32, /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, @@ -3166,6 +3174,7 @@ pub const Inst = struct { fields_hash_1: u32, fields_hash_2: u32, fields_hash_3: u32, + src_line: u32, /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, @@ -3195,6 +3204,7 @@ pub const Inst = struct { /// 2. capture: Capture, // for every captures_len /// 3. decl: Index, // for every decls_len; points to a `declaration` instruction pub const OpaqueDecl = struct { + src_line: u32, /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, diff --git a/src/Module.zig b/src/Module.zig index f857d0997b9a..31b022fd370d 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -88,6 +88,9 @@ export_owners: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Exp /// an update is requested, as well as to cache `@import` results. /// Keys are fully resolved file paths. This table owns the keys and values. import_table: std.StringArrayHashMapUnmanaged(*File) = .{}, +/// This acts as a map from `path_digest` to the corresponding `File`. +/// The value is omitted, as keys are ordered identically to `import_table`. +path_digest_map: std.AutoArrayHashMapUnmanaged(Cache.BinDigest, void) = .{}, /// The set of all the files which have been loaded with `@embedFile` in the Module. /// We keep track of this in order to iterate over it and check which files have been /// modified on the file system when an update is requested, as well as to cache @@ -735,8 +738,7 @@ pub const File = struct { /// List of references to this file, used for multi-package errors. references: std.ArrayListUnmanaged(Reference) = .{}, /// The hash of the path to this file, used to store `InternPool.TrackedInst`. - /// undefined until `zir_loaded == true`. - path_digest: Cache.BinDigest = undefined, + path_digest: Cache.BinDigest, /// The most recent successful ZIR for this file, with no errors. /// This is only populated when a previously successful ZIR @@ -2357,10 +2359,10 @@ pub const LazySrcLoc = struct { 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; + const file = file: { + const index = zcu.path_digest_map.getIndex(want_path_digest).?; + break :file zcu.import_table.values()[index]; + }; assert(file.zir_loaded); const zir = file.zir; @@ -2432,6 +2434,7 @@ pub fn deinit(zcu: *Zcu) void { value.destroy(zcu); } zcu.import_table.deinit(gpa); + zcu.path_digest_map.deinit(gpa); for (zcu.embed_table.keys(), zcu.embed_table.values()) |path, embed_file| { gpa.free(path); @@ -2596,26 +2599,12 @@ pub fn astGenFile(mod: *Module, file: *File) !void { const stat = try source_file.stat(); const want_local_cache = file.mod == mod.main_mod; - const bin_digest = hash: { - var path_hash: Cache.HashHelper = .{}; - path_hash.addBytes(build_options.version); - path_hash.add(builtin.zig_backend); - if (!want_local_cache) { - path_hash.addOptionalBytes(file.mod.root.root_dir.path); - path_hash.addBytes(file.mod.root.sub_path); - } - path_hash.addBytes(file.sub_file_path); - var bin: Cache.BinDigest = undefined; - path_hash.hasher.final(&bin); - break :hash bin; - }; - file.path_digest = bin_digest; const hex_digest = hex: { var hex: Cache.HexDigest = undefined; _ = std.fmt.bufPrint( &hex, "{s}", - .{std.fmt.fmtSliceHexLower(&bin_digest)}, + .{std.fmt.fmtSliceHexLower(&file.path_digest)}, ) catch unreachable; break :hex hex; }; @@ -4122,12 +4111,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { var block_scope: Sema.Block = .{ .parent = null, .sema = &sema, - .src_decl = decl_index, .namespace = decl.src_namespace, .instructions = .{}, .inlining = null, .is_comptime = true, .src_base_inst = decl.zir_decl_index.unwrap().?, + .type_name_ctx = decl.name, }; defer block_scope.instructions.deinit(gpa); @@ -4355,6 +4344,7 @@ pub fn importPkg(zcu: *Zcu, mod: *Package.Module) !ImportFileResult { keep_resolved_path = true; // It's now owned by import_table. gop.value_ptr.* = builtin_file; try builtin_file.addReference(zcu.*, .{ .root = mod }); + try zcu.path_digest_map.put(gpa, builtin_file.path_digest, {}); return .{ .file = builtin_file, .is_new = false, @@ -4382,8 +4372,23 @@ pub fn importPkg(zcu: *Zcu, mod: *Package.Module) !ImportFileResult { .status = .never_loaded, .mod = mod, .root_decl = .none, + .path_digest = digest: { + const want_local_cache = mod == zcu.main_mod; + var path_hash: Cache.HashHelper = .{}; + path_hash.addBytes(build_options.version); + path_hash.add(builtin.zig_backend); + if (!want_local_cache) { + path_hash.addOptionalBytes(mod.root.root_dir.path); + path_hash.addBytes(mod.root.sub_path); + } + path_hash.addBytes(sub_file_path); + var bin: Cache.BinDigest = undefined; + path_hash.hasher.final(&bin); + break :digest bin; + }, }; try new_file.addReference(zcu.*, .{ .root = mod }); + try zcu.path_digest_map.put(gpa, new_file.path_digest, {}); return ImportFileResult{ .file = new_file, .is_new = true, @@ -4392,23 +4397,23 @@ pub fn importPkg(zcu: *Zcu, mod: *Package.Module) !ImportFileResult { } pub fn importFile( - mod: *Module, + zcu: *Zcu, cur_file: *File, import_string: []const u8, ) !ImportFileResult { if (std.mem.eql(u8, import_string, "std")) { - return mod.importPkg(mod.std_mod); + return zcu.importPkg(zcu.std_mod); } if (std.mem.eql(u8, import_string, "root")) { - return mod.importPkg(mod.root_mod); + return zcu.importPkg(zcu.root_mod); } if (cur_file.mod.deps.get(import_string)) |pkg| { - return mod.importPkg(pkg); + return zcu.importPkg(pkg); } if (!mem.endsWith(u8, import_string, ".zig")) { return error.ModuleNotFound; } - const gpa = mod.gpa; + const gpa = zcu.gpa; // The resolved path is used as the key in the import table, to detect if // an import refers to the same as another, despite different relative paths @@ -4424,8 +4429,8 @@ pub fn importFile( var keep_resolved_path = false; defer if (!keep_resolved_path) gpa.free(resolved_path); - const gop = try mod.import_table.getOrPut(gpa, resolved_path); - errdefer _ = mod.import_table.pop(); + const gop = try zcu.import_table.getOrPut(gpa, resolved_path); + errdefer _ = zcu.import_table.pop(); if (gop.found_existing) return ImportFileResult{ .file = gop.value_ptr.*, .is_new = false, @@ -4470,7 +4475,22 @@ pub fn importFile( .status = .never_loaded, .mod = cur_file.mod, .root_decl = .none, + .path_digest = digest: { + const want_local_cache = cur_file.mod == zcu.main_mod; + var path_hash: Cache.HashHelper = .{}; + path_hash.addBytes(build_options.version); + path_hash.add(builtin.zig_backend); + if (!want_local_cache) { + path_hash.addOptionalBytes(cur_file.mod.root.root_dir.path); + path_hash.addBytes(cur_file.mod.root.sub_path); + } + path_hash.addBytes(sub_file_path); + var bin: Cache.BinDigest = undefined; + path_hash.hasher.final(&bin); + break :digest bin; + }, }; + try zcu.path_digest_map.put(gpa, new_file.path_digest, {}); return ImportFileResult{ .file = new_file, .is_new = true, @@ -5039,7 +5059,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato var inner_block: Sema.Block = .{ .parent = null, .sema = &sema, - .src_decl = decl_index, .namespace = decl.src_namespace, .instructions = .{}, .inlining = null, @@ -5052,6 +5071,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato const orig_decl = mod.declPtr(owner_info.owner_decl); break :inst orig_decl.zir_decl_index.unwrap().?; }, + .type_name_ctx = decl.name, }; defer inner_block.instructions.deinit(gpa); diff --git a/src/Sema.zig b/src/Sema.zig index aa4d459f1bc7..c8a8aeeb9114 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16,9 +16,7 @@ air_instructions: std.MultiArrayList(Air.Inst) = .{}, air_extra: std.ArrayListUnmanaged(u32) = .{}, /// Maps ZIR to AIR. inst_map: InstMap = .{}, -/// When analyzing an inline function call, owner_decl is the Decl of the caller -/// and `src_decl` of `Block` is the `Decl` of the callee. -/// This `Decl` owns the arena memory of this `Sema`. +/// When analyzing an inline function call, owner_decl is the Decl of the caller. owner_decl: *Decl, owner_decl_index: InternPool.DeclIndex, /// For an inline or comptime function call, this will be the root parent function @@ -342,7 +340,6 @@ pub const Block = struct { /// Shared among all child blocks. sema: *Sema, /// The namespace to use for lookups from this source block - /// When analyzing fields, this is different from src_decl.src_namespace. namespace: InternPool.NamespaceIndex, /// The AIR instructions generated for this block. instructions: std.ArrayListUnmanaged(Air.Inst.Index), @@ -360,10 +357,6 @@ pub const Block = struct { /// If runtime_index is not 0 then one of these is guaranteed to be non 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. - src_decl: InternPool.DeclIndex, /// Non zero if a non-inline loop or a runtime conditional have been encountered. /// Stores to comptime variables are only allowed when var.runtime_index <= runtime_index. runtime_index: Value.RuntimeIndex = .zero, @@ -396,6 +389,12 @@ pub const Block = struct { /// treated as relative to the AST node of this ZIR instruction. src_base_inst: InternPool.TrackedInst.Index, + /// The name of the current "context" for naming namespace types. + /// The interpretation of this depends on the name strategy in ZIR, but the name + /// is always incorporated into the type name somehow. + /// See `Sema.createAnonymousDeclTypeNamed`. + type_name_ctx: InternPool.NullTerminatedString, + /// 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 { @@ -516,7 +515,6 @@ pub const Block = struct { return .{ .parent = parent, .sema = parent.sema, - .src_decl = parent.src_decl, .namespace = parent.namespace, .instructions = .{}, .label = null, @@ -533,6 +531,7 @@ pub const Block = struct { .error_return_trace_index = parent.error_return_trace_index, .need_debug_scope = parent.need_debug_scope, .src_base_inst = parent.src_base_inst, + .type_name_ctx = parent.type_name_ctx, }; } @@ -993,9 +992,11 @@ fn analyzeBodyInner( while (true) { crash_info.setBodyIndex(i); const inst = body[i]; - std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{ - mod.namespacePtr(mod.declPtr(block.src_decl).src_namespace).file_scope.sub_file_path, inst, - }); + std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{ sub_file_path: { + const path_digest = block.src_base_inst.resolveFull(&mod.intern_pool).path_digest; + const index = mod.path_digest_map.getIndex(path_digest).?; + break :sub_file_path mod.import_table.values()[index].sub_file_path; + }, inst }); const air_inst: Air.Inst.Ref = switch (tags[@intFromEnum(inst)]) { // zig fmt: off .alloc => try sema.zirAlloc(block, inst), @@ -2821,6 +2822,7 @@ fn zirStructDecl( small.name_strategy, "struct", inst, + extra.data.src_line, ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -2857,20 +2859,19 @@ fn createAnonymousDeclTypeNamed( name_strategy: Zir.Inst.NameStrategy, anon_prefix: []const u8, inst: ?Zir.Inst.Index, + src_line: u32, ) !InternPool.DeclIndex { const zcu = sema.mod; const ip = &zcu.intern_pool; const gpa = sema.gpa; const namespace = block.namespace; - const src_decl = zcu.declPtr(block.src_decl); const new_decl_index = try zcu.allocateNewDecl(namespace); errdefer zcu.destroyDecl(new_decl_index); switch (name_strategy) { .anon => {}, // handled after switch .parent => { - const name = zcu.declPtr(block.src_decl).name; - try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); + try zcu.initNewAnonDecl(new_decl_index, src_line, val, block.type_name_ctx); return new_decl_index; }, .func => func_strat: { @@ -2881,7 +2882,7 @@ fn createAnonymousDeclTypeNamed( defer buf.deinit(); const writer = buf.writer(); - try writer.print("{}(", .{zcu.declPtr(block.src_decl).name.fmt(ip)}); + try writer.print("{}(", .{block.type_name_ctx.fmt(ip)}); var arg_i: usize = 0; for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) { @@ -2915,7 +2916,7 @@ fn createAnonymousDeclTypeNamed( try writer.writeByte(')'); const name = try ip.getOrPutString(gpa, buf.items, .no_embedded_nulls); - try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); + try zcu.initNewAnonDecl(new_decl_index, src_line, val, name); return new_decl_index; }, .dbg_var => { @@ -2927,9 +2928,9 @@ fn createAnonymousDeclTypeNamed( if (zir_data[i].str_op.operand != ref) continue; const name = try ip.getOrPutStringFmt(gpa, "{}.{s}", .{ - src_decl.name.fmt(ip), zir_data[i].str_op.getStr(sema.code), + block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), }, .no_embedded_nulls); - try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); + try zcu.initNewAnonDecl(new_decl_index, src_line, val, name); return new_decl_index; }, else => {}, @@ -2948,9 +2949,9 @@ fn createAnonymousDeclTypeNamed( // renamed. const name = ip.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ - src_decl.name.fmt(ip), anon_prefix, @intFromEnum(new_decl_index), + block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(new_decl_index), }, .no_embedded_nulls) catch unreachable; - try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); + try zcu.initNewAnonDecl(new_decl_index, src_line, val, name); return new_decl_index; } @@ -3056,6 +3057,7 @@ fn zirEnumDecl( small.name_strategy, "enum", inst, + extra.data.src_line, ); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; @@ -3112,12 +3114,12 @@ fn zirEnumDecl( var enum_block: Block = .{ .parent = null, .sema = sema, - .src_decl = new_decl_index, .namespace = new_namespace_index.unwrap() orelse block.namespace, .instructions = .{}, .inlining = null, .is_comptime = true, .src_base_inst = tracked_inst, + .type_name_ctx = new_decl.name, }; defer enum_block.instructions.deinit(sema.gpa); @@ -3323,6 +3325,7 @@ fn zirUnionDecl( small.name_strategy, "union", inst, + extra.data.src_line, ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -3411,6 +3414,7 @@ fn zirOpaqueDecl( small.name_strategy, "opaque", inst, + extra.data.src_line, ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -5942,7 +5946,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr var child_block: Block = .{ .parent = parent_block, .sema = sema, - .src_decl = parent_block.src_decl, .namespace = parent_block.namespace, .instructions = .{}, .inlining = parent_block.inlining, @@ -5953,6 +5956,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr .runtime_loop = parent_block.runtime_loop, .runtime_index = parent_block.runtime_index, .src_base_inst = parent_block.src_base_inst, + .type_name_ctx = parent_block.type_name_ctx, }; defer child_block.instructions.deinit(gpa); @@ -6063,7 +6067,6 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt var child_block: Block = .{ .parent = parent_block, .sema = sema, - .src_decl = parent_block.src_decl, .namespace = parent_block.namespace, .instructions = .{}, .label = &label, @@ -6079,6 +6082,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt .runtime_index = parent_block.runtime_index, .error_return_trace_index = parent_block.error_return_trace_index, .src_base_inst = parent_block.src_base_inst, + .type_name_ctx = parent_block.type_name_ctx, }; defer child_block.instructions.deinit(gpa); @@ -6726,7 +6730,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .no_embedded_nulls, ); const decl_index = try sema.lookupIdentifier(block, src, decl_name); - try sema.addReferencedBy(block, src, decl_index); + try sema.addReferencedBy(src, decl_index); return sema.analyzeDeclRef(decl_index); } @@ -7695,7 +7699,6 @@ fn analyzeCall( var child_block: Block = .{ .parent = null, .sema = sema, - .src_decl = module_fn.owner_decl, .namespace = fn_owner_decl.src_namespace, .instructions = .{}, .label = null, @@ -7708,6 +7711,7 @@ fn analyzeCall( .runtime_loop = block.runtime_loop, .runtime_index = block.runtime_index, .src_base_inst = fn_owner_decl.zir_decl_index.unwrap().?, + .type_name_ctx = fn_owner_decl.name, }; const merges = &child_block.inlining.?.merges; @@ -8217,12 +8221,12 @@ fn instantiateGenericCall( var child_block: Block = .{ .parent = null, .sema = &child_sema, - .src_decl = generic_owner_func.owner_decl, .namespace = namespace_index, .instructions = .{}, .inlining = null, .is_comptime = true, .src_base_inst = fn_owner_decl.zir_decl_index.unwrap().?, + .type_name_ctx = fn_owner_decl.name, }; defer child_block.instructions.deinit(gpa); @@ -8366,7 +8370,7 @@ fn instantiateGenericCall( const callee = mod.funcInfo(callee_index); callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota); - try sema.addReferencedBy(block, call_src, callee.owner_decl); + try sema.addReferencedBy(call_src, callee.owner_decl); // Make a runtime call to the new function, making sure to omit the comptime args. const func_ty = Type.fromInterned(callee.ty); @@ -9346,7 +9350,7 @@ fn zirFunc( // If this instruction has a body it means it's the type of the `owner_decl` // otherwise it's a function type without a `callconv` attribute and should // never be `.C`. - const cc: std.builtin.CallingConvention = if (has_body and mod.declPtr(block.src_decl).is_exported) + const cc: std.builtin.CallingConvention = if (has_body and mod.declPtr(sema.owner_decl_index).is_exported) .C else .Unspecified; @@ -11595,7 +11599,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp var child_block: Block = .{ .parent = block, .sema = sema, - .src_decl = block.src_decl, .namespace = block.namespace, .instructions = .{}, .label = &label, @@ -11610,6 +11613,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp .error_return_trace_index = block.error_return_trace_index, .want_safety = block.want_safety, .src_base_inst = block.src_base_inst, + .type_name_ctx = block.type_name_ctx, }; const merges = &child_block.label.?.merges; defer child_block.instructions.deinit(gpa); @@ -12327,7 +12331,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r var child_block: Block = .{ .parent = block, .sema = sema, - .src_decl = block.src_decl, .namespace = block.namespace, .instructions = .{}, .label = &label, @@ -12342,6 +12345,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r .want_safety = block.want_safety, .error_return_trace_index = block.error_return_trace_index, .src_base_inst = block.src_base_inst, + .type_name_ctx = block.type_name_ctx, }; const merges = &child_block.label.?.merges; defer child_block.instructions.deinit(gpa); @@ -18843,7 +18847,6 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr var child_block: Block = .{ .parent = block, .sema = sema, - .src_decl = block.src_decl, .namespace = block.namespace, .instructions = .{}, .inlining = block.inlining, @@ -18852,6 +18855,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr .want_safety = false, .error_return_trace_index = block.error_return_trace_index, .src_base_inst = block.src_base_inst, + .type_name_ctx = block.type_name_ctx, }; defer child_block.instructions.deinit(sema.gpa); @@ -18922,7 +18926,6 @@ fn zirTypeofPeer( var child_block: Block = .{ .parent = block, .sema = sema, - .src_decl = block.src_decl, .namespace = block.namespace, .instructions = .{}, .inlining = block.inlining, @@ -18932,6 +18935,7 @@ fn zirTypeofPeer( .runtime_loop = block.runtime_loop, .runtime_index = block.runtime_index, .src_base_inst = block.src_base_inst, + .type_name_ctx = block.type_name_ctx, }; defer child_block.instructions.deinit(sema.gpa); // Ignore the result, we only care about the instructions in `args`. @@ -19398,13 +19402,13 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label .block = .{ .parent = block, .sema = sema, - .src_decl = block.src_decl, .namespace = block.namespace, .instructions = .{}, .label = &labeled_block.label, .inlining = block.inlining, .is_comptime = block.is_comptime, .src_base_inst = block.src_base_inst, + .type_name_ctx = block.type_name_ctx, }, }; sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block); @@ -21201,7 +21205,7 @@ fn zirReify( const gpa = sema.gpa; 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 extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data; const src = block.nodeOffset(extra.node); const type_info_ty = try sema.getBuiltinType("Type"); const uncasted_operand = try sema.resolveInst(extra.operand); @@ -21521,7 +21525,7 @@ fn zirReify( .needed_comptime_reason = "struct fields must be comptime-known", }); - return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_arr, name_strategy, is_tuple_val.toBool()); + return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_arr, name_strategy, is_tuple_val.toBool(), extra.src_line); }, .Enum => { const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); @@ -21550,7 +21554,7 @@ fn zirReify( .needed_comptime_reason = "enum fields must be comptime-known", }); - return sema.reifyEnum(block, inst, src, tag_type_val.toType(), is_exhaustive_val.toBool(), fields_arr, name_strategy); + return sema.reifyEnum(block, inst, src, tag_type_val.toType(), is_exhaustive_val.toBool(), fields_arr, name_strategy, extra.src_line); }, .Opaque => { const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); @@ -21581,6 +21585,7 @@ fn zirReify( name_strategy, "opaque", inst, + extra.src_line, ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -21617,7 +21622,7 @@ fn zirReify( .needed_comptime_reason = "union fields must be comptime-known", }); - return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_arr, name_strategy); + return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_arr, name_strategy, extra.src_line); }, .Fn => { const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); @@ -21719,6 +21724,7 @@ fn reifyEnum( is_exhaustive: bool, fields_val: Value, name_strategy: Zir.Inst.NameStrategy, + src_line: u32, ) CompileError!Air.Inst.Ref { const mod = sema.mod; const gpa = sema.gpa; @@ -21780,6 +21786,7 @@ fn reifyEnum( name_strategy, "enum", inst, + src_line, ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -21843,6 +21850,7 @@ fn reifyUnion( opt_tag_type_val: Value, fields_val: Value, name_strategy: Zir.Inst.NameStrategy, + src_line: u32, ) CompileError!Air.Inst.Ref { const mod = sema.mod; const gpa = sema.gpa; @@ -21926,6 +21934,7 @@ fn reifyUnion( name_strategy, "union", inst, + src_line, ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -22021,7 +22030,7 @@ fn reifyUnion( } } - const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), mod.declPtr(new_decl_index)); + const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), mod.declPtr(new_decl_index), src_line); break :tag_ty .{ enum_tag_ty, false }; }; errdefer if (!has_explicit_tag) ip.remove(enum_tag_ty); // remove generated tag type on error @@ -22082,6 +22091,7 @@ fn reifyStruct( fields_val: Value, name_strategy: Zir.Inst.NameStrategy, is_tuple: bool, + src_line: u32, ) CompileError!Air.Inst.Ref { const mod = sema.mod; const gpa = sema.gpa; @@ -22182,6 +22192,7 @@ fn reifyStruct( name_strategy, "struct", inst, + src_line, ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -26903,12 +26914,12 @@ fn addSafetyCheck( var fail_block: Block = .{ .parent = parent_block, .sema = sema, - .src_decl = parent_block.src_decl, .namespace = parent_block.namespace, .instructions = .{}, .inlining = parent_block.inlining, .is_comptime = false, .src_base_inst = parent_block.src_base_inst, + .type_name_ctx = parent_block.type_name_ctx, }; defer fail_block.instructions.deinit(gpa); @@ -27012,12 +27023,12 @@ fn panicUnwrapError( var fail_block: Block = .{ .parent = parent_block, .sema = sema, - .src_decl = parent_block.src_decl, .namespace = parent_block.namespace, .instructions = .{}, .inlining = parent_block.inlining, .is_comptime = false, .src_base_inst = parent_block.src_base_inst, + .type_name_ctx = parent_block.type_name_ctx, }; defer fail_block.instructions.deinit(gpa); @@ -27129,12 +27140,12 @@ fn safetyCheckFormatted( var fail_block: Block = .{ .parent = parent_block, .sema = sema, - .src_decl = parent_block.src_decl, .namespace = parent_block.namespace, .instructions = .{}, .inlining = parent_block.inlining, .is_comptime = false, .src_base_inst = parent_block.src_base_inst, + .type_name_ctx = parent_block.type_name_ctx, }; defer fail_block.instructions.deinit(gpa); @@ -27682,7 +27693,7 @@ fn fieldCallBind( const decl_idx = (try sema.namespaceLookup(block, src, namespace, field_name)) orelse break :found_decl null; - try sema.addReferencedBy(block, src, decl_idx); + try sema.addReferencedBy(src, decl_idx); const decl_val = try sema.analyzeDeclVal(block, src, decl_idx); const decl_type = sema.typeOf(decl_val); if (mod.typeToFunc(decl_type)) |func_type| f: { @@ -27838,7 +27849,7 @@ fn namespaceLookupRef( decl_name: InternPool.NullTerminatedString, ) CompileError!?Air.Inst.Ref { const decl = (try sema.namespaceLookup(block, src, opt_namespace, decl_name)) orelse return null; - try sema.addReferencedBy(block, src, decl); + try sema.addReferencedBy(src, decl); return try sema.analyzeDeclRef(decl); } @@ -31757,7 +31768,7 @@ fn analyzeDeclVal( src: LazySrcLoc, decl_index: InternPool.DeclIndex, ) CompileError!Air.Inst.Ref { - try sema.addReferencedBy(block, src, decl_index); + try sema.addReferencedBy(src, decl_index); if (sema.decl_val_table.get(decl_index)) |result| { return result; } @@ -31773,13 +31784,14 @@ fn analyzeDeclVal( fn addReferencedBy( sema: *Sema, - block: *Block, src: LazySrcLoc, decl_index: InternPool.DeclIndex, ) !void { if (sema.mod.comp.reference_trace == 0) return; try sema.mod.reference_table.put(sema.gpa, decl_index, .{ - .referencer = block.src_decl, + // TODO: this can make the reference trace suboptimal. This will be fixed + // once the reference table is reworked for incremental compilation. + .referencer = sema.owner_decl_index, .src = src, }); } @@ -35181,12 +35193,12 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co var block: Block = .{ .parent = null, .sema = &sema, - .src_decl = decl_index, .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace, .instructions = .{}, .inlining = null, .is_comptime = true, .src_base_inst = struct_type.zir_index.unwrap().?, + .type_name_ctx = decl.name, }; defer assert(block.instructions.items.len == 0); @@ -36036,12 +36048,12 @@ fn semaStructFields( var block_scope: Block = .{ .parent = null, .sema = &sema, - .src_decl = decl_index, .namespace = namespace_index, .instructions = .{}, .inlining = null, .is_comptime = true, .src_base_inst = struct_type.zir_index.unwrap().?, + .type_name_ctx = decl.name, }; defer assert(block_scope.instructions.items.len == 0); @@ -36247,12 +36259,12 @@ fn semaStructFieldInits( var block_scope: Block = .{ .parent = null, .sema = &sema, - .src_decl = decl_index, .namespace = namespace_index, .instructions = .{}, .inlining = null, .is_comptime = true, .src_base_inst = struct_type.zir_index.unwrap().?, + .type_name_ctx = decl.name, }; defer assert(block_scope.instructions.items.len == 0); @@ -36359,7 +36371,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; assert(extended.opcode == .union_decl); const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); - var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len; + const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); + var extra_index: usize = extra.end; const tag_type_ref: Zir.Inst.Ref = if (small.has_tag_type) blk: { const ty_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); @@ -36421,12 +36434,12 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded var block_scope: Block = .{ .parent = null, .sema = &sema, - .src_decl = decl_index, .namespace = union_type.namespace.unwrap().?, .instructions = .{}, .inlining = null, .is_comptime = true, .src_base_inst = union_type.zir_index, + .type_name_ctx = decl.name, }; defer assert(block_scope.instructions.items.len == 0); @@ -36711,10 +36724,10 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded return sema.failWithOwnedErrorMsg(&block_scope, msg); } } else if (enum_field_vals.count() > 0) { - const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), mod.declPtr(union_type.decl)); + const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), mod.declPtr(union_type.decl), extra.data.src_line); union_type.tagTypePtr(ip).* = enum_ty; } else { - const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, mod.declPtr(union_type.decl)); + const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, mod.declPtr(union_type.decl), extra.data.src_line); union_type.tagTypePtr(ip).* = enum_ty; } } @@ -36732,12 +36745,12 @@ fn generateUnionTagTypeNumbered( enum_field_names: []const InternPool.NullTerminatedString, enum_field_vals: []const InternPool.Index, union_owner_decl: *Module.Decl, + src_line: u32, ) !InternPool.Index { const mod = sema.mod; const gpa = sema.gpa; const ip = &mod.intern_pool; - const src_decl = mod.declPtr(block.src_decl); const new_decl_index = try mod.allocateNewDecl(block.namespace); errdefer mod.destroyDecl(new_decl_index); const fqn = try union_owner_decl.fullyQualifiedName(mod); @@ -36749,7 +36762,7 @@ fn generateUnionTagTypeNumbered( ); try mod.initNewAnonDecl( new_decl_index, - src_decl.src_line, + src_line, Value.@"unreachable", name, ); @@ -36782,6 +36795,7 @@ fn generateUnionTagTypeSimple( block: *Block, enum_field_names: []const InternPool.NullTerminatedString, union_owner_decl: *Module.Decl, + src_line: u32, ) !InternPool.Index { const mod = sema.mod; const ip = &mod.intern_pool; @@ -36789,7 +36803,6 @@ 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); errdefer mod.destroyDecl(new_decl_index); const name = try ip.getOrPutStringFmt( @@ -36800,7 +36813,7 @@ fn generateUnionTagTypeSimple( ); try mod.initNewAnonDecl( new_decl_index, - src_decl.src_line, + src_line, Value.@"unreachable", name, ); @@ -36835,7 +36848,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { var block: Block = .{ .parent = null, .sema = sema, - .src_decl = sema.owner_decl_index, .namespace = sema.owner_decl.src_namespace, .instructions = .{}, .inlining = null, @@ -36853,6 +36865,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { else => unreachable, } }, + .type_name_ctx = sema.owner_decl.name, }; defer block.instructions.deinit(sema.gpa); @@ -36898,7 +36911,6 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { var block: Block = .{ .parent = null, .sema = sema, - .src_decl = sema.owner_decl_index, .namespace = sema.owner_decl.src_namespace, .instructions = .{}, .inlining = null, @@ -36916,6 +36928,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { else => unreachable, } }, + .type_name_ctx = sema.owner_decl.name, }; defer block.instructions.deinit(sema.gpa); diff --git a/src/crash_report.zig b/src/crash_report.zig index ed45c32681ac..db1d4846e9b4 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -81,7 +81,7 @@ fn dumpStatusReport() !void { 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 writeFilePath(file, stderr); try stderr.writeAll("\n"); print_zir.renderInstructionContext( @@ -105,7 +105,7 @@ fn dumpStatusReport() !void { fba.reset(); try stderr.writeAll(" in "); 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 writeFilePath(cur_block_file, stderr); try stderr.writeAll("\n > "); print_zir.renderSingleInstruction( allocator, @@ -140,13 +140,6 @@ fn writeFilePath(file: *Module.File, writer: anytype) !void { try writer.writeAll(file.sub_file_path); } -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); -} - pub fn compilerPanic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, maybe_ret_addr: ?usize) noreturn { PanicSwitch.preDispatch(); @setCold(true); diff --git a/src/main.zig b/src/main.zig index 21f7281d74f6..083954b80911 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5965,6 +5965,7 @@ fn cmdAstCheck( .zir = undefined, .mod = undefined, .root_decl = .none, + .path_digest = undefined, }; if (zig_source_file) |file_name| { var f = fs.cwd().openFile(file_name, .{}) catch |err| { @@ -6283,6 +6284,7 @@ fn cmdDumpZir( .zir = try Module.loadZirCache(gpa, f), .mod = undefined, .root_decl = .none, + .path_digest = undefined, }; defer file.zir.deinit(gpa); @@ -6353,6 +6355,7 @@ fn cmdChangelist( .zir = undefined, .mod = undefined, .root_decl = .none, + .path_digest = undefined, }; file.mod = try Package.Module.createLimited(arena, .{ diff --git a/src/print_zir.zig b/src/print_zir.zig index e2d2f6e5000b..0e2fe17736d8 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -569,7 +569,6 @@ const Writer = struct { .wasm_memory_size, .int_from_error, .error_from_int, - .reify, .c_va_copy, .c_va_end, .work_item_id, @@ -582,6 +581,14 @@ const Writer = struct { try self.writeSrcNode(stream, inst_data.node); }, + .reify => { + const inst_data = self.code.extraData(Zir.Inst.Reify, extended.operand).data; + try stream.print("{d}, ", .{inst_data.src_line}); + try self.writeInstRef(stream, inst_data.operand); + try stream.writeAll(")) "); + try self.writeSrcNode(stream, inst_data.node); + }, + .builtin_extern, .c_define, .error_cast, From f37d0725fa4c6a0b5e4e9ca4d25e2760dc06764d Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 17 Jun 2024 20:01:50 +0100 Subject: [PATCH 05/10] Sema: fix callconv detection in generic functions When analyzing `zirFunc` to instantiate a generic function, `sema.owner_decl` is not the owner Decl of the generic instance, but instead of the call site, so that dependencies are propagated correctly. (This aligns with the fact that in future, generic instantiations will not have a corresponding `Cau`.) So, when deciding the callconv in this case, we must check `sema.generic_owner` to determine whether the function is exported. --- src/Sema.zig | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index c8a8aeeb9114..6714af768566 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9347,13 +9347,17 @@ fn zirFunc( src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data; } - // If this instruction has a body it means it's the type of the `owner_decl` - // otherwise it's a function type without a `callconv` attribute and should - // never be `.C`. - const cc: std.builtin.CallingConvention = if (has_body and mod.declPtr(sema.owner_decl_index).is_exported) - .C - else - .Unspecified; + // If this instruction has a body, then it's a function declaration, and we decide + // the callconv based on whether it is exported. Otherwise, the callconv defaults + // to `.Unspecified`. + const cc: std.builtin.CallingConvention = if (has_body) cc: { + const fn_is_exported = if (sema.generic_owner != .none) exported: { + const generic_owner_fn = mod.funcInfo(sema.generic_owner); + const generic_owner_decl = mod.declPtr(generic_owner_fn.owner_decl); + break :exported generic_owner_decl.is_exported; + } else sema.owner_decl.is_exported; + break :cc if (fn_is_exported) .C else .Unspecified; + } else .Unspecified; return sema.funcCommon( block, From edf14777bae56c3a6a155c59f793dc432656c1de Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 18 Jun 2024 04:30:06 +0100 Subject: [PATCH 06/10] link.Wasm: correctly fetch source location when decl is a type The comment explains the situation here. This is a bit of a hack, and should be reworked when `Decl` is properly split up. --- src/link/Wasm/ZigObject.zig | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/link/Wasm/ZigObject.zig b/src/link/Wasm/ZigObject.zig index 7d9e7e1310f3..cced85f80095 100644 --- a/src/link/Wasm/ZigObject.zig +++ b/src/link/Wasm/ZigObject.zig @@ -484,7 +484,17 @@ 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.navSrcLoc(mod).upgrade(mod))) { + // We want to lower the source location of `decl`. However, when generating + // lazy functions (for e.g. `@tagName`), `decl` may correspond to a type + // rather than a `Nav`! + // The future split of `Decl` into `Nav` and `Cau` may require rethinking this + // logic. For now, just get the source location conditionally as needed. + const decl_src = if (decl.typeOf(mod).toIntern() == .type_type) + decl.val.toType().srcLoc(mod) + else + decl.navSrcLoc(mod); + + switch (try zig_object.lowerConst(wasm_file, name, val, decl_src.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); From 0486aa5081eee589edce79b721f35fadf2de1625 Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 18 Jun 2024 04:41:02 +0100 Subject: [PATCH 07/10] Zir: provide absolute node for `reify` Since we track `reify` instructions across incremental updates, it is acceptable to treat it as the baseline for a relative source location. This turns out to be a good idea, since it makes it easy to define the source location for a reified type. --- lib/std/zig/AstGen.zig | 5 +++-- lib/std/zig/Zir.zig | 4 +++- src/Module.zig | 1 + src/Sema.zig | 16 ++++++++++++++-- src/print_zir.zig | 5 ++++- src/type.zig | 19 ++++--------------- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 40fcf562798c..b135c7188a29 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -9361,9 +9361,10 @@ fn builtinCall( try gz.instructions.ensureUnusedCapacity(gpa, 1); try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); - const payload_index = try gz.astgen.addExtra(Zir.Inst.UnNode{ - .node = gz.nodeIndexToRelative(node), + const payload_index = try gz.astgen.addExtra(Zir.Inst.Reify{ + .node = node, // Absolute node index -- see the definition of `Reify`. .operand = operand, + .src_line = astgen.source_line, }); const new_index: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len); gz.astgen.instructions.appendAssumeCapacity(.{ diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 69fc2b9b76fd..57518f82e0c4 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -2835,7 +2835,9 @@ pub const Inst = struct { }; pub const Reify = struct { - node: i32, + /// This node is absolute, because `reify` instructions are tracked across updates, and + /// this simplifies the logic for getting source locations for types. + node: Ast.Node.Index, operand: Ref, src_line: u32, }; diff --git a/src/Module.zig b/src/Module.zig index 31b022fd370d..3faa1b878047 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2374,6 +2374,7 @@ pub const LazySrcLoc = struct { .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, + .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node, else => unreachable, }, else => unreachable, diff --git a/src/Sema.zig b/src/Sema.zig index 6714af768566..c34004e20052 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -21210,10 +21210,22 @@ fn zirReify( const ip = &mod.intern_pool; const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); const extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data; - const src = block.nodeOffset(extra.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 operand_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ + .node_offset_builtin_call_arg = .{ + .builtin_call_node = 0, // `tracked_inst` is precisely the `reify` instruction, so offset is 0 + .arg_index = 0, + }, + }, + }; const type_info_ty = try sema.getBuiltinType("Type"); const uncasted_operand = try sema.resolveInst(extra.operand); - 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", diff --git a/src/print_zir.zig b/src/print_zir.zig index 0e2fe17736d8..b32ea5ffe9d4 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -586,7 +586,10 @@ const Writer = struct { try stream.print("{d}, ", .{inst_data.src_line}); try self.writeInstRef(stream, inst_data.operand); try stream.writeAll(")) "); - try self.writeSrcNode(stream, inst_data.node); + const prev_parent_decl_node = self.parent_decl_node; + self.parent_decl_node = inst_data.node; + defer self.parent_decl_node = prev_parent_decl_node; + try self.writeSrcNode(stream, 0); }, .builtin_extern, diff --git a/src/type.zig b/src/type.zig index 546234db378e..215320ad791e 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3336,22 +3336,11 @@ pub const Type = struct { 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().?, + .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) { + .declared => |d| d.zir_index, + .reified => |r| r.zir_index, .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, // must be declared since we can't generate tags when reifying - else => return null, + .empty_struct => return null, }, else => return null, }, From 75395c99c5be28987670dcc8383cec3b38b5a83f Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 18 Jun 2024 04:44:39 +0100 Subject: [PATCH 08/10] Zir: track reifications across updates This was always necessary, it was just missing logic. It is necessary due to type equivalence rules. --- lib/std/zig/Zir.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 57518f82e0c4..5dd69f9923de 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -3738,6 +3738,7 @@ fn findDeclsInner( .union_decl, .enum_decl, .opaque_decl, + .reify, => return list.append(inst), else => return, From 6a8cf25a8aea11ef80b48c9bce59d0aafcff3297 Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 18 Jun 2024 04:55:39 +0100 Subject: [PATCH 09/10] cases: un-regress some notes Since we now have source locations for reified types again, some error notes have returned which were previously regressed by this branch. --- .../compile_errors/comptime_arg_to_generic_fn_callee_error.zig | 1 + .../reify_type_for_tagged_union_with_extra_enum_field.zig | 2 ++ .../reify_type_for_tagged_union_with_extra_union_field.zig | 1 + .../reify_type_for_tagged_union_with_no_enum_fields.zig | 1 + .../reify_type_for_tagged_union_with_no_union_fields.zig | 3 +++ 5 files changed, 8 insertions(+) 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 8d8516eecc8d..efc3f556a943 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,3 +18,4 @@ 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/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 25b58e7c29cd..0ea0b019b9c4 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,3 +31,5 @@ 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 dd324f751cb1..ed6f2245d4b2 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,3 +31,4 @@ 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 188b4d9d6a66..91c5354c0cb1 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,3 +27,4 @@ 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 5c367e9ba656..2dc983247062 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,3 +27,6 @@ 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 From 2b677d1660018434757f9c9efec3c712675e6c47 Mon Sep 17 00:00:00 2001 From: mlugg Date: Thu, 20 Jun 2024 08:38:23 +0100 Subject: [PATCH 10/10] Sema: fix performance regression LLVM fails to notice that in release builds, `logFn` ignores its arguments, so their computation can be elided. So, LLVM fails to elide this hashmap lookup. Its cost isn't too significant, but doing it in the hottest loop in Sema adds up! Technically, we could do the lookup a single time, before the loop, but it was cleanest (and a little faster) to just disable this log call at comptime when debug logging is disabled. --- src/Sema.zig | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index c34004e20052..a5c94eb57cbe 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -992,11 +992,16 @@ fn analyzeBodyInner( while (true) { crash_info.setBodyIndex(i); const inst = body[i]; - std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{ sub_file_path: { - const path_digest = block.src_base_inst.resolveFull(&mod.intern_pool).path_digest; - const index = mod.path_digest_map.getIndex(path_digest).?; - break :sub_file_path mod.import_table.values()[index].sub_file_path; - }, inst }); + + // The hashmap lookup in here is a little expensive, and LLVM fails to optimize it away. + if (build_options.enable_logging) { + std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{ sub_file_path: { + const path_digest = block.src_base_inst.resolveFull(&mod.intern_pool).path_digest; + const index = mod.path_digest_map.getIndex(path_digest).?; + break :sub_file_path mod.import_table.values()[index].sub_file_path; + }, inst }); + } + const air_inst: Air.Inst.Ref = switch (tags[@intFromEnum(inst)]) { // zig fmt: off .alloc => try sema.zirAlloc(block, inst),