aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2024-06-14 23:05:39 +0100
committermlugg <mlugg@mlugg.co.uk>2024-06-15 00:57:52 +0100
commit1eaeb4a0a838a783d2060f4e5b3b26b483b26009 (patch)
tree16fc6b1e9279a6c19e9d41574e4c304e2f387d42 /src/Module.zig
parent07a24bec9a578857920f4c5508f1d7eea65177b8 (diff)
downloadzig-1eaeb4a0a838a783d2060f4e5b3b26b483b26009.tar.gz
zig-1eaeb4a0a838a783d2060f4e5b3b26b483b26009.zip
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.
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig1805
1 files changed, 772 insertions, 1033 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 283a4f75cc..f857d0997b 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -107,8 +107,17 @@ intern_pool: InternPool = .{},
/// a Decl can have a failed_decls entry but have analysis status of success.
failed_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, *ErrorMsg) = .{},
/// Keep track of one `@compileLog` callsite per owner Decl.
-/// The value is the AST node index offset from the Decl.
-compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, i32) = .{},
+/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`.
+compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, extern struct {
+ base_node_inst: InternPool.TrackedInst.Index,
+ node_offset: i32,
+ pub fn src(self: @This()) LazySrcLoc {
+ return .{
+ .base_node_inst = self.base_node_inst,
+ .offset = LazySrcLoc.Offset.nodeOffset(self.node_offset),
+ };
+ }
+}) = .{},
/// Using a map here for consistency with the other fields here.
/// The ErrorMsg memory is owned by the `File`, using Module's general purpose allocator.
failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{},
@@ -257,9 +266,6 @@ pub const Export = struct {
src: LazySrcLoc,
/// The Decl that performs the export. Note that this is *not* the Decl being exported.
owner_decl: Decl.Index,
- /// The Decl containing the export statement. Inline function calls
- /// may cause this to be different from the owner_decl.
- src_decl: Decl.Index,
exported: Exported,
status: enum {
in_progress,
@@ -278,12 +284,7 @@ pub const Export = struct {
};
pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc {
- const src_decl = mod.declPtr(exp.src_decl);
- return .{
- .file_scope = src_decl.getFileScope(mod),
- .parent_decl_node = src_decl.src_node,
- .lazy = exp.src,
- };
+ return exp.src.upgrade(mod);
}
};
@@ -343,9 +344,6 @@ pub const Decl = struct {
/// there is no parent.
src_namespace: Namespace.Index,
- /// The AST node index of this declaration.
- /// Must be recomputed when the corresponding source file is modified.
- src_node: Ast.Node.Index,
/// Line number corresponding to `src_node`. Stored separately so that source files
/// do not need to be loaded into memory in order to compute debug line numbers.
/// This value is absolute.
@@ -417,26 +415,6 @@ pub const Decl = struct {
return extra.data.getBodies(@intCast(extra.end), zir);
}
- pub fn relativeToNodeIndex(decl: Decl, offset: i32) Ast.Node.Index {
- return @bitCast(offset + @as(i32, @bitCast(decl.src_node)));
- }
-
- pub fn nodeIndexToRelative(decl: Decl, node_index: Ast.Node.Index) i32 {
- return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(decl.src_node));
- }
-
- pub fn srcLoc(decl: Decl, zcu: *Zcu) SrcLoc {
- return decl.nodeOffsetSrcLoc(0, zcu);
- }
-
- pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32, zcu: *Zcu) SrcLoc {
- return .{
- .file_scope = decl.getFileScope(zcu),
- .parent_decl_node = decl.src_node,
- .lazy = LazySrcLoc.nodeOffset(node_offset),
- };
- }
-
pub fn renderFullyQualifiedName(decl: Decl, zcu: *Zcu, writer: anytype) !void {
if (decl.name_fully_qualified) {
try writer.print("{}", .{decl.name.fmt(&zcu.intern_pool)});
@@ -551,101 +529,6 @@ pub const Decl = struct {
return decl.typeOf(zcu).abiAlignment(zcu);
}
- /// Upgrade a `LazySrcLoc` to a `SrcLoc` based on the `Decl` provided.
- pub fn toSrcLoc(decl: *Decl, lazy: LazySrcLoc, mod: *Module) SrcLoc {
- return switch (lazy) {
- .unneeded,
- .entire_file,
- .byte_abs,
- .token_abs,
- .node_abs,
- => .{
- .file_scope = decl.getFileScope(mod),
- .parent_decl_node = 0,
- .lazy = lazy,
- },
-
- .byte_offset,
- .token_offset,
- .node_offset,
- .node_offset_main_token,
- .node_offset_initializer,
- .node_offset_var_decl_ty,
- .node_offset_var_decl_align,
- .node_offset_var_decl_section,
- .node_offset_var_decl_addrspace,
- .node_offset_var_decl_init,
- .node_offset_builtin_call_arg0,
- .node_offset_builtin_call_arg1,
- .node_offset_builtin_call_arg2,
- .node_offset_builtin_call_arg3,
- .node_offset_builtin_call_arg4,
- .node_offset_builtin_call_arg5,
- .node_offset_ptrcast_operand,
- .node_offset_array_access_index,
- .node_offset_slice_ptr,
- .node_offset_slice_start,
- .node_offset_slice_end,
- .node_offset_slice_sentinel,
- .node_offset_call_func,
- .node_offset_field_name,
- .node_offset_field_name_init,
- .node_offset_deref_ptr,
- .node_offset_asm_source,
- .node_offset_asm_ret_ty,
- .node_offset_if_cond,
- .node_offset_bin_op,
- .node_offset_bin_lhs,
- .node_offset_bin_rhs,
- .node_offset_switch_operand,
- .node_offset_switch_special_prong,
- .node_offset_switch_range,
- .node_offset_switch_prong_capture,
- .node_offset_switch_prong_tag_capture,
- .node_offset_fn_type_align,
- .node_offset_fn_type_addrspace,
- .node_offset_fn_type_section,
- .node_offset_fn_type_cc,
- .node_offset_fn_type_ret_ty,
- .node_offset_param,
- .token_offset_param,
- .node_offset_anyframe_type,
- .node_offset_lib_name,
- .node_offset_array_type_len,
- .node_offset_array_type_sentinel,
- .node_offset_array_type_elem,
- .node_offset_un_op,
- .node_offset_ptr_elem,
- .node_offset_ptr_sentinel,
- .node_offset_ptr_align,
- .node_offset_ptr_addrspace,
- .node_offset_ptr_bitoffset,
- .node_offset_ptr_hostsize,
- .node_offset_container_tag,
- .node_offset_field_default,
- .node_offset_init_ty,
- .node_offset_store_ptr,
- .node_offset_store_operand,
- .node_offset_return_operand,
- .for_input,
- .for_capture_from_input,
- .array_cat_lhs,
- .array_cat_rhs,
- => .{
- .file_scope = decl.getFileScope(mod),
- .parent_decl_node = decl.src_node,
- .lazy = lazy,
- },
- inline .call_arg,
- .fn_proto_param,
- => |x| .{
- .file_scope = decl.getFileScope(mod),
- .parent_decl_node = mod.declPtr(x.decl).src_node,
- .lazy = lazy,
- },
- };
- }
-
pub fn declPtrType(decl: Decl, zcu: *Zcu) !Type {
assert(decl.has_tv);
const decl_ty = decl.typeOf(zcu);
@@ -661,6 +544,23 @@ pub const Decl = struct {
},
});
}
+
+ /// Returns the source location of this `Decl`.
+ /// Asserts that this `Decl` corresponds to what will in future be a `Nav` (Named
+ /// Addressable Value): a source-level declaration or generic instantiation.
+ pub fn navSrcLoc(decl: Decl, zcu: *Zcu) LazySrcLoc {
+ return .{
+ .base_node_inst = decl.zir_decl_index.unwrap() orelse inst: {
+ // generic instantiation
+ assert(decl.has_tv);
+ assert(decl.owns_tv);
+ const owner = zcu.funcInfo(decl.val.toIntern()).generic_owner;
+ const generic_owner_decl = zcu.declPtr(zcu.funcInfo(owner).owner_decl);
+ break :inst generic_owner_decl.zir_decl_index.unwrap().?;
+ },
+ .offset = LazySrcLoc.Offset.nodeOffset(0),
+ };
+ }
};
/// This state is attached to every Decl when Module emit_h is non-null.
@@ -1137,18 +1037,17 @@ pub const ErrorMsg = struct {
/// Canonical reference to a position within a source file.
pub const SrcLoc = struct {
file_scope: *File,
- /// Might be 0 depending on tag of `lazy`.
- parent_decl_node: Ast.Node.Index,
- /// Relative to `parent_decl_node`.
- lazy: LazySrcLoc,
+ base_node: Ast.Node.Index,
+ /// Relative to `base_node`.
+ lazy: LazySrcLoc.Offset,
- pub fn declSrcToken(src_loc: SrcLoc) Ast.TokenIndex {
+ pub fn baseSrcToken(src_loc: SrcLoc) Ast.TokenIndex {
const tree = src_loc.file_scope.tree;
- return tree.firstToken(src_loc.parent_decl_node);
+ return tree.firstToken(src_loc.base_node);
}
- pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index {
- return @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node)));
+ pub fn relativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index {
+ return @bitCast(offset + @as(i32, @bitCast(src_loc.base_node)));
}
pub const Span = Ast.Span;
@@ -1172,14 +1071,14 @@ pub const SrcLoc = struct {
},
.byte_offset => |byte_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const tok_index = src_loc.declSrcToken();
+ const tok_index = src_loc.baseSrcToken();
const start = tree.tokens.items(.start)[tok_index] + byte_off;
const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
return Span{ .start = start, .end = end, .main = start };
},
.token_offset => |tok_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const tok_index = src_loc.declSrcToken() + tok_off;
+ const tok_index = src_loc.baseSrcToken() + tok_off;
const start = tree.tokens.items(.start)[tok_index];
const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
return Span{ .start = start, .end = end, .main = start };
@@ -1187,25 +1086,25 @@ pub const SrcLoc = struct {
.node_offset => |traced_off| {
const node_off = traced_off.x;
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
assert(src_loc.file_scope.tree_loaded);
return tree.nodeToSpan(node);
},
.node_offset_main_token => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const main_token = tree.nodes.items(.main_token)[node];
return tree.tokensToSpan(main_token, main_token, main_token);
},
.node_offset_bin_op => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
assert(src_loc.file_scope.tree_loaded);
return tree.nodeToSpan(node);
},
.node_offset_initializer => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
return tree.tokensToSpan(
tree.firstToken(node) - 3,
tree.lastToken(node),
@@ -1214,7 +1113,7 @@ pub const SrcLoc = struct {
},
.node_offset_var_decl_ty => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const node_tags = tree.nodes.items(.tag);
const full = switch (node_tags[node]) {
.global_var_decl,
@@ -1238,41 +1137,51 @@ pub const SrcLoc = struct {
},
.node_offset_var_decl_align => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullVarDecl(node).?;
return tree.nodeToSpan(full.ast.align_node);
},
.node_offset_var_decl_section => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullVarDecl(node).?;
return tree.nodeToSpan(full.ast.section_node);
},
.node_offset_var_decl_addrspace => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullVarDecl(node).?;
return tree.nodeToSpan(full.ast.addrspace_node);
},
.node_offset_var_decl_init => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullVarDecl(node).?;
return tree.nodeToSpan(full.ast.init_node);
},
- .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0),
- .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1),
- .node_offset_builtin_call_arg2 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 2),
- .node_offset_builtin_call_arg3 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 3),
- .node_offset_builtin_call_arg4 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 4),
- .node_offset_builtin_call_arg5 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 5),
+ .node_offset_builtin_call_arg => |builtin_arg| {
+ const tree = try src_loc.file_scope.getTree(gpa);
+ const node_datas = tree.nodes.items(.data);
+ const node_tags = tree.nodes.items(.tag);
+ const node = src_loc.relativeToNodeIndex(builtin_arg.builtin_call_node);
+ const param = switch (node_tags[node]) {
+ .builtin_call_two, .builtin_call_two_comma => switch (builtin_arg.arg_index) {
+ 0 => node_datas[node].lhs,
+ 1 => node_datas[node].rhs,
+ else => unreachable,
+ },
+ .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + builtin_arg.arg_index],
+ else => unreachable,
+ };
+ return tree.nodeToSpan(param);
+ },
.node_offset_ptrcast_operand => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const main_tokens = tree.nodes.items(.main_token);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
- var node = src_loc.declRelativeToNodeIndex(node_off);
+ var node = src_loc.relativeToNodeIndex(node_off);
while (true) {
switch (node_tags[node]) {
.builtin_call_two, .builtin_call_two_comma => {},
@@ -1304,7 +1213,7 @@ pub const SrcLoc = struct {
.node_offset_array_access_index => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
return tree.nodeToSpan(node_datas[node].rhs);
},
.node_offset_slice_ptr,
@@ -1313,7 +1222,7 @@ pub const SrcLoc = struct {
.node_offset_slice_sentinel,
=> |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullSlice(node).?;
const part_node = switch (src_loc.lazy) {
.node_offset_slice_ptr => full.ast.sliced,
@@ -1326,7 +1235,7 @@ pub const SrcLoc = struct {
},
.node_offset_call_func => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullCall(&buf, node).?;
return tree.nodeToSpan(full.ast.fn_expr);
@@ -1335,7 +1244,7 @@ pub const SrcLoc = struct {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
var buf: [1]Ast.Node.Index = undefined;
const tok_index = switch (node_tags[node]) {
.field_access => node_datas[node].rhs,
@@ -1359,7 +1268,7 @@ pub const SrcLoc = struct {
},
.node_offset_field_name_init => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const tok_index = tree.firstToken(node) - 2;
const start = tree.tokens.items(.start)[tok_index];
const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
@@ -1367,18 +1276,18 @@ pub const SrcLoc = struct {
},
.node_offset_deref_ptr => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
return tree.nodeToSpan(node);
},
.node_offset_asm_source => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullAsm(node).?;
return tree.nodeToSpan(full.ast.template);
},
.node_offset_asm_ret_ty => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullAsm(node).?;
const asm_output = full.outputs[0];
const node_datas = tree.nodes.items(.data);
@@ -1387,7 +1296,7 @@ pub const SrcLoc = struct {
.node_offset_if_cond => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const node_tags = tree.nodes.items(.tag);
const src_node = switch (node_tags[node]) {
.if_simple,
@@ -1416,7 +1325,7 @@ pub const SrcLoc = struct {
},
.for_input => |for_input| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(for_input.for_node_offset);
+ const node = src_loc.relativeToNodeIndex(for_input.for_node_offset);
const for_full = tree.fullFor(node).?;
const src_node = for_full.ast.inputs[for_input.input_index];
return tree.nodeToSpan(src_node);
@@ -1424,7 +1333,7 @@ pub const SrcLoc = struct {
.for_capture_from_input => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const token_tags = tree.tokens.items(.tag);
- const input_node = src_loc.declRelativeToNodeIndex(node_off);
+ const input_node = src_loc.relativeToNodeIndex(node_off);
// We have to actually linear scan the whole AST to find the for loop
// that contains this input.
const node_tags = tree.nodes.items(.tag);
@@ -1465,7 +1374,7 @@ pub const SrcLoc = struct {
},
.call_arg => |call_arg| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset);
+ const node = src_loc.relativeToNodeIndex(call_arg.call_node_offset);
var buf: [2]Ast.Node.Index = undefined;
const call_full = tree.fullCall(buf[0..1], node) orelse {
const node_tags = tree.nodes.items(.tag);
@@ -1501,43 +1410,49 @@ pub const SrcLoc = struct {
};
return tree.nodeToSpan(call_full.ast.params[call_arg.arg_index]);
},
- .fn_proto_param => |fn_proto_param| {
+ .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(fn_proto_param.fn_proto_node_offset);
+ const node = src_loc.relativeToNodeIndex(fn_proto_param.fn_proto_node_offset);
var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?;
var it = full.iterate(tree);
var i: usize = 0;
while (it.next()) |param| : (i += 1) {
- if (i == fn_proto_param.param_index) {
- if (param.anytype_ellipsis3) |token| return tree.tokenToSpan(token);
- const first_token = param.comptime_noalias orelse
- param.name_token orelse
- tree.firstToken(param.type_expr);
- return tree.tokensToSpan(
- first_token,
- tree.lastToken(param.type_expr),
- first_token,
- );
+ if (i != fn_proto_param.param_index) continue;
+
+ switch (src_loc.lazy) {
+ .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| {
+ return tree.tokenToSpan(tok);
+ } else {
+ return tree.nodeToSpan(param.type_expr);
+ },
+ .fn_proto_param => if (param.anytype_ellipsis3) |tok| {
+ const first = param.comptime_noalias orelse param.name_token orelse tok;
+ return tree.tokensToSpan(first, tok, first);
+ } else {
+ const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr);
+ return tree.tokensToSpan(first, tree.lastToken(param.type_expr), first);
+ },
+ else => unreachable,
}
}
unreachable;
},
.node_offset_bin_lhs => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const node_datas = tree.nodes.items(.data);
return tree.nodeToSpan(node_datas[node].lhs);
},
.node_offset_bin_rhs => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const node_datas = tree.nodes.items(.data);
return tree.nodeToSpan(node_datas[node].rhs);
},
.array_cat_lhs, .array_cat_rhs => |cat| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(cat.array_cat_offset);
+ const node = src_loc.relativeToNodeIndex(cat.array_cat_offset);
const node_datas = tree.nodes.items(.data);
const arr_node = if (src_loc.lazy == .array_cat_lhs)
node_datas[node].lhs
@@ -1565,14 +1480,14 @@ pub const SrcLoc = struct {
.node_offset_switch_operand => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const node_datas = tree.nodes.items(.data);
return tree.nodeToSpan(node_datas[node].lhs);
},
.node_offset_switch_special_prong => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const switch_node = src_loc.declRelativeToNodeIndex(node_off);
+ const switch_node = src_loc.relativeToNodeIndex(node_off);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const main_tokens = tree.nodes.items(.main_token);
@@ -1592,7 +1507,7 @@ pub const SrcLoc = struct {
.node_offset_switch_range => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const switch_node = src_loc.declRelativeToNodeIndex(node_off);
+ const switch_node = src_loc.relativeToNodeIndex(node_off);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const main_tokens = tree.nodes.items(.main_token);
@@ -1613,56 +1528,30 @@ pub const SrcLoc = struct {
}
} else unreachable;
},
- .node_offset_switch_prong_capture,
- .node_offset_switch_prong_tag_capture,
- => |node_off| {
- const tree = try src_loc.file_scope.getTree(gpa);
- const case_node = src_loc.declRelativeToNodeIndex(node_off);
- const case = tree.fullSwitchCase(case_node).?;
- const token_tags = tree.tokens.items(.tag);
- const start_tok = switch (src_loc.lazy) {
- .node_offset_switch_prong_capture => case.payload_token.?,
- .node_offset_switch_prong_tag_capture => blk: {
- var tok = case.payload_token.?;
- if (token_tags[tok] == .asterisk) tok += 1;
- tok += 2; // skip over comma
- break :blk tok;
- },
- else => unreachable,
- };
- const end_tok = switch (token_tags[start_tok]) {
- .asterisk => start_tok + 1,
- else => start_tok,
- };
- const start = tree.tokens.items(.start)[start_tok];
- const end_start = tree.tokens.items(.start)[end_tok];
- const end = end_start + @as(u32, @intCast(tree.tokenSlice(end_tok).len));
- return Span{ .start = start, .end = end, .main = start };
- },
.node_offset_fn_type_align => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.align_expr);
},
.node_offset_fn_type_addrspace => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.addrspace_expr);
},
.node_offset_fn_type_section => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.section_expr);
},
.node_offset_fn_type_cc => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.callconv_expr);
@@ -1670,7 +1559,7 @@ pub const SrcLoc = struct {
.node_offset_fn_type_ret_ty => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.return_type);
@@ -1678,7 +1567,7 @@ pub const SrcLoc = struct {
.node_offset_param => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const token_tags = tree.tokens.items(.tag);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
var first_tok = tree.firstToken(node);
while (true) switch (token_tags[first_tok - 1]) {
@@ -1694,7 +1583,7 @@ pub const SrcLoc = struct {
.token_offset_param => |token_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const token_tags = tree.tokens.items(.tag);
- const main_token = tree.nodes.items(.main_token)[src_loc.parent_decl_node];
+ const main_token = tree.nodes.items(.main_token)[src_loc.base_node];
const tok_index = @as(Ast.TokenIndex, @bitCast(token_off + @as(i32, @bitCast(main_token))));
var first_tok = tok_index;
@@ -1712,13 +1601,13 @@ pub const SrcLoc = struct {
.node_offset_anyframe_type => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
return tree.nodeToSpan(node_datas[parent_node].rhs);
},
.node_offset_lib_name => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, parent_node).?;
const tok_index = full.lib_name.?;
@@ -1729,21 +1618,21 @@ pub const SrcLoc = struct {
.node_offset_array_type_len => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullArrayType(parent_node).?;
return tree.nodeToSpan(full.ast.elem_count);
},
.node_offset_array_type_sentinel => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullArrayType(parent_node).?;
return tree.nodeToSpan(full.ast.sentinel);
},
.node_offset_array_type_elem => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullArrayType(parent_node).?;
return tree.nodeToSpan(full.ast.elem_type);
@@ -1751,48 +1640,48 @@ pub const SrcLoc = struct {
.node_offset_un_op => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
return tree.nodeToSpan(node_datas[node].lhs);
},
.node_offset_ptr_elem => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullPtrType(parent_node).?;
return tree.nodeToSpan(full.ast.child_type);
},
.node_offset_ptr_sentinel => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullPtrType(parent_node).?;
return tree.nodeToSpan(full.ast.sentinel);
},
.node_offset_ptr_align => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullPtrType(parent_node).?;
return tree.nodeToSpan(full.ast.align_node);
},
.node_offset_ptr_addrspace => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullPtrType(parent_node).?;
return tree.nodeToSpan(full.ast.addrspace_node);
},
.node_offset_ptr_bitoffset => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullPtrType(parent_node).?;
return tree.nodeToSpan(full.ast.bit_range_start);
},
.node_offset_ptr_hostsize => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full = tree.fullPtrType(parent_node).?;
return tree.nodeToSpan(full.ast.bit_range_end);
@@ -1800,7 +1689,7 @@ pub const SrcLoc = struct {
.node_offset_container_tag => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
switch (node_tags[parent_node]) {
.container_decl_arg, .container_decl_arg_trailing => {
@@ -1822,7 +1711,7 @@ pub const SrcLoc = struct {
.node_offset_field_default => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
const full: Ast.full.ContainerField = switch (node_tags[parent_node]) {
.container_field => tree.containerField(parent_node),
@@ -1833,7 +1722,7 @@ pub const SrcLoc = struct {
},
.node_offset_init_ty => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ const parent_node = src_loc.relativeToNodeIndex(node_off);
var buf: [2]Ast.Node.Index = undefined;
const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init|
@@ -1846,7 +1735,7 @@ pub const SrcLoc = struct {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const node_datas = tree.nodes.items(.data);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
switch (node_tags[node]) {
.assign => {
@@ -1859,7 +1748,7 @@ pub const SrcLoc = struct {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const node_datas = tree.nodes.items(.data);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
switch (node_tags[node]) {
.assign => {
@@ -1870,7 +1759,7 @@ pub const SrcLoc = struct {
},
.node_offset_return_operand => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
- const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node = src_loc.relativeToNodeIndex(node_off);
const node_tags = tree.nodes.items(.tag);
const node_datas = tree.nodes.items(.data);
if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) {
@@ -1878,381 +1767,629 @@ pub const SrcLoc = struct {
}
return tree.nodeToSpan(node);
},
- }
- }
+ .container_field_name,
+ .container_field_value,
+ .container_field_type,
+ .container_field_align,
+ => |field_idx| {
+ const tree = try src_loc.file_scope.getTree(gpa);
+ const node = src_loc.relativeToNodeIndex(0);
+ var buf: [2]Ast.Node.Index = undefined;
+ const container_decl = tree.fullContainerDecl(&buf, node) orelse
+ return tree.nodeToSpan(node);
+
+ 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());
}