Skip to content

Commit a01d2ab

Browse files
authored
Merge pull request #14210 from Vexu/compile-errors
improve struct/union field error locations
2 parents b3e495a + f2faa30 commit a01d2ab

22 files changed

+449
-424
lines changed

src/AstGen.zig

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,7 +2013,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
20132013
},
20142014
.local_val => scope = scope.cast(Scope.LocalVal).?.parent,
20152015
.local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2016-
.namespace => break,
2016+
.namespace, .enum_namespace => break,
20172017
.defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
20182018
.top => unreachable,
20192019
}
@@ -2088,7 +2088,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
20882088
try parent_gz.addDefer(defer_scope.index, defer_scope.len);
20892089
},
20902090
.defer_error => scope = scope.cast(Scope.Defer).?.parent,
2091-
.namespace => break,
2091+
.namespace, .enum_namespace => break,
20922092
.top => unreachable,
20932093
}
20942094
}
@@ -2179,7 +2179,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke
21792179
.local_val => scope = scope.cast(Scope.LocalVal).?.parent,
21802180
.local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
21812181
.defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2182-
.namespace => break,
2182+
.namespace, .enum_namespace => break,
21832183
.top => unreachable,
21842184
}
21852185
}
@@ -2729,7 +2729,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct {
27292729
const have_err_payload = defer_scope.remapped_err_code != 0;
27302730
need_err_code = need_err_code or have_err_payload;
27312731
},
2732-
.namespace => unreachable,
2732+
.namespace, .enum_namespace => unreachable,
27332733
.top => unreachable,
27342734
}
27352735
}
@@ -2799,7 +2799,7 @@ fn genDefers(
27992799
.normal_only => continue,
28002800
}
28012801
},
2802-
.namespace => unreachable,
2802+
.namespace, .enum_namespace => unreachable,
28032803
.top => unreachable,
28042804
}
28052805
}
@@ -2835,7 +2835,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v
28352835
scope = s.parent;
28362836
},
28372837
.defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2838-
.namespace => unreachable,
2838+
.namespace, .enum_namespace => unreachable,
28392839
.top => unreachable,
28402840
}
28412841
}
@@ -4278,7 +4278,7 @@ fn testDecl(
42784278
.local_val, .local_ptr => unreachable, // a test cannot be in a local scope
42794279
.gen_zir => s = s.cast(GenZir).?.parent,
42804280
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
4281-
.namespace => {
4281+
.namespace, .enum_namespace => {
42824282
const ns = s.cast(Scope.Namespace).?;
42834283
if (ns.decls.get(name_str_index)) |i| {
42844284
if (found_already) |f| {
@@ -4963,6 +4963,7 @@ fn containerDecl(
49634963
defer block_scope.unstack();
49644964

49654965
_ = try astgen.scanDecls(&namespace, container_decl.ast.members);
4966+
namespace.base.tag = .enum_namespace;
49664967

49674968
const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
49684969
try comptimeExpr(&block_scope, &namespace.base, .{ .rl = .{ .ty = .type_type } }, container_decl.ast.arg)
@@ -4977,6 +4978,7 @@ fn containerDecl(
49774978
for (container_decl.ast.members) |member_node| {
49784979
if (member_node == counts.nonexhaustive_node)
49794980
continue;
4981+
namespace.base.tag = .namespace;
49804982
var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
49814983
.decl => continue,
49824984
.field => |field| field,
@@ -5010,6 +5012,7 @@ fn containerDecl(
50105012
},
50115013
);
50125014
}
5015+
namespace.base.tag = .enum_namespace;
50135016
const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);
50145017
wip_members.appendToField(@enumToInt(tag_value_inst));
50155018
}
@@ -7296,7 +7299,7 @@ fn localVarRef(
72967299
},
72977300
.gen_zir => s = s.cast(GenZir).?.parent,
72987301
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
7299-
.namespace => {
7302+
.namespace, .enum_namespace => {
73007303
const ns = s.cast(Scope.Namespace).?;
73017304
if (ns.decls.get(name_str_index)) |i| {
73027305
if (found_already) |f| {
@@ -7308,7 +7311,7 @@ fn localVarRef(
73087311
// We found a match but must continue looking for ambiguous references to decls.
73097312
found_already = i;
73107313
}
7311-
num_namespaces_out += 1;
7314+
if (s.tag == .namespace) num_namespaces_out += 1;
73127315
capturing_namespace = ns;
73137316
s = ns.parent;
73147317
},
@@ -7935,7 +7938,7 @@ fn builtinCall(
79357938
},
79367939
.gen_zir => s = s.cast(GenZir).?.parent,
79377940
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
7938-
.namespace => {
7941+
.namespace, .enum_namespace => {
79397942
const ns = s.cast(Scope.Namespace).?;
79407943
if (ns.decls.get(decl_name)) |i| {
79417944
if (found_already) |f| {
@@ -10547,6 +10550,12 @@ const Scope = struct {
1054710550
else => return null,
1054810551
}
1054910552
}
10553+
if (T == Namespace) {
10554+
switch (base.tag) {
10555+
.namespace, .enum_namespace => return @fieldParentPtr(T, "base", base),
10556+
else => return null,
10557+
}
10558+
}
1055010559
if (base.tag != T.base_tag)
1055110560
return null;
1055210561

@@ -10559,7 +10568,7 @@ const Scope = struct {
1055910568
.local_val => base.cast(LocalVal).?.parent,
1056010569
.local_ptr => base.cast(LocalPtr).?.parent,
1056110570
.defer_normal, .defer_error => base.cast(Defer).?.parent,
10562-
.namespace => base.cast(Namespace).?.parent,
10571+
.namespace, .enum_namespace => base.cast(Namespace).?.parent,
1056310572
.top => null,
1056410573
};
1056510574
}
@@ -10571,6 +10580,7 @@ const Scope = struct {
1057110580
defer_normal,
1057210581
defer_error,
1057310582
namespace,
10583+
enum_namespace,
1057410584
top,
1057510585
};
1057610586

@@ -12247,7 +12257,7 @@ fn detectLocalShadowing(
1224712257
}
1224812258
s = local_ptr.parent;
1224912259
},
12250-
.namespace => {
12260+
.namespace, .enum_namespace => {
1225112261
outer_scope = true;
1225212262
const ns = s.cast(Scope.Namespace).?;
1225312263
const decl_node = ns.decls.get(ident_name) orelse {
@@ -12415,7 +12425,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
1241512425
}
1241612426
s = local_ptr.parent;
1241712427
},
12418-
.namespace => s = s.cast(Scope.Namespace).?.parent,
12428+
.namespace, .enum_namespace => s = s.cast(Scope.Namespace).?.parent,
1241912429
.gen_zir => s = s.cast(GenZir).?.parent,
1242012430
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
1242112431
.top => break,

src/Module.zig

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,49 @@ pub const EnumFull = struct {
11941194
.lazy = LazySrcLoc.nodeOffset(0),
11951195
};
11961196
}
1197+
1198+
pub fn fieldSrcLoc(e: EnumFull, mod: *Module, query: FieldSrcQuery) SrcLoc {
1199+
@setCold(true);
1200+
const owner_decl = mod.declPtr(e.owner_decl);
1201+
const file = owner_decl.getFileScope();
1202+
const tree = file.getTree(mod.gpa) catch |err| {
1203+
// In this case we emit a warning + a less precise source location.
1204+
log.warn("unable to load {s}: {s}", .{
1205+
file.sub_file_path, @errorName(err),
1206+
});
1207+
return e.srcLoc(mod);
1208+
};
1209+
const node = owner_decl.relativeToNodeIndex(0);
1210+
const node_tags = tree.nodes.items(.tag);
1211+
switch (node_tags[node]) {
1212+
.container_decl,
1213+
.container_decl_trailing,
1214+
=> return queryFieldSrc(tree.*, query, file, tree.containerDecl(node)),
1215+
.container_decl_two, .container_decl_two_trailing => {
1216+
var buffer: [2]Ast.Node.Index = undefined;
1217+
return queryFieldSrc(tree.*, query, file, tree.containerDeclTwo(&buffer, node));
1218+
},
1219+
.container_decl_arg,
1220+
.container_decl_arg_trailing,
1221+
=> return queryFieldSrc(tree.*, query, file, tree.containerDeclArg(node)),
1222+
1223+
.tagged_union,
1224+
.tagged_union_trailing,
1225+
=> return queryFieldSrc(tree.*, query, file, tree.taggedUnion(node)),
1226+
.tagged_union_two, .tagged_union_two_trailing => {
1227+
var buffer: [2]Ast.Node.Index = undefined;
1228+
return queryFieldSrc(tree.*, query, file, tree.taggedUnionTwo(&buffer, node));
1229+
},
1230+
.tagged_union_enum_tag,
1231+
.tagged_union_enum_tag_trailing,
1232+
=> return queryFieldSrc(tree.*, query, file, tree.taggedUnionEnumTag(node)),
1233+
1234+
.root => return queryFieldSrc(tree.*, query, file, tree.containerDeclRoot()),
1235+
1236+
// This struct was generated using @Type
1237+
else => return e.srcLoc(mod),
1238+
}
1239+
}
11971240
};
11981241

11991242
pub const Union = struct {
@@ -3519,14 +3562,6 @@ pub fn deinit(mod: *Module) void {
35193562
pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
35203563
const gpa = mod.gpa;
35213564
{
3522-
if (mod.failed_decls.contains(decl_index)) {
3523-
blk: {
3524-
const errs = mod.comp.getAllErrorsAlloc() catch break :blk;
3525-
for (errs.list) |err| Compilation.AllErrors.Message.renderToStdErr(err, .no_color);
3526-
}
3527-
// TODO restore test case triggering this panic
3528-
@panic("Zig compiler bug: attempted to destroy declaration with an attached error");
3529-
}
35303565
const decl = mod.declPtr(decl_index);
35313566
log.debug("destroy {*} ({s})", .{ decl, decl.name });
35323567
_ = mod.test_functions.swapRemove(decl_index);
@@ -6179,7 +6214,7 @@ pub const PeerTypeCandidateSrc = union(enum) {
61796214

61806215
const FieldSrcQuery = struct {
61816216
index: usize,
6182-
range: enum { name, type, value, alignment },
6217+
range: enum { name, type, value, alignment } = .name,
61836218
};
61846219

61856220
fn queryFieldSrc(
@@ -6749,3 +6784,25 @@ pub fn getDeclExports(mod: Module, decl_index: Decl.Index) []const *Export {
67496784
return &[0]*Export{};
67506785
}
67516786
}
6787+
6788+
pub const Feature = enum {
6789+
panic_fn,
6790+
panic_unwrap_error,
6791+
safety_check_formatted,
6792+
error_return_trace,
6793+
is_named_enum_value,
6794+
error_set_has_value,
6795+
};
6796+
6797+
pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {
6798+
return switch (feature) {
6799+
.panic_fn => mod.comp.bin_file.options.target.ofmt == .c or
6800+
mod.comp.bin_file.options.use_llvm,
6801+
.panic_unwrap_error => mod.comp.bin_file.options.target.ofmt == .c or
6802+
mod.comp.bin_file.options.use_llvm,
6803+
.safety_check_formatted => mod.comp.bin_file.options.use_llvm,
6804+
.error_return_trace => mod.comp.bin_file.options.use_llvm,
6805+
.is_named_enum_value => mod.comp.bin_file.options.use_llvm,
6806+
.error_set_has_value => mod.comp.bin_file.options.use_llvm,
6807+
};
6808+
}

0 commit comments

Comments
 (0)