authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-05 20:05:14-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-01-05 20:05:14-07:00
loga01d2ab0e3d5d571c95fb7c188642c1cdd7b9552
tree6e9857e76304e4bad2a989ea71e40300afd62f42
parentb3e495a38a5e334f5e30e255592f810e0017919c
parentf2faa303a541f5adddbba26d04dc2749991e0075
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14210 from Vexu/compile-errors

improve struct/union field error locations

22 files changed, 449 insertions(+), 424 deletions(-)

src/AstGen.zig+23-13
......@@ -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+66-9
......@@ -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
11991242pub const Union = struct {
......@@ -3519,14 +3562,6 @@ pub fn deinit(mod: *Module) void {
35193562pub 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
61806215const FieldSrcQuery = struct {
61816216 index: usize,
6182 range: enum { name, type, value, alignment },
6217 range: enum { name, type, value, alignment } = .name,
61836218};
61846219
61856220fn queryFieldSrc(
......@@ -6749,3 +6784,25 @@ pub fn getDeclExports(mod: Module, decl_index: Decl.Index) []const *Export {
67496784 return &[0]*Export{};
67506785 }
67516786}
6787
6788pub 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
6797pub 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}
src/Sema.zig+251-315
......@@ -1820,12 +1820,7 @@ fn analyzeAsType(
18201820}
18211821
18221822pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void {
1823 const backend_supports_error_return_tracing =
1824 sema.mod.comp.bin_file.options.use_llvm;
1825 if (!backend_supports_error_return_tracing) {
1826 // TODO implement this feature in all the backends and then delete this branch
1827 return;
1828 }
1823 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
18291824
18301825 assert(!block.is_comptime);
18311826 var err_trace_block = block.makeSubBlock();
......@@ -2099,16 +2094,12 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS
20992094 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});
21002095 errdefer msg.destroy(sema.gpa);
21012096
2102 const decl_index = container_ty.getOwnerDeclOrNull() orelse break :msg msg;
2103 const decl = sema.mod.declPtr(decl_index);
2104 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {
2105 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
2106 return error.AnalysisFail;
2107 };
2108 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_index);
2109 const default_value_src: LazySrcLoc = .{ .node_offset_field_default = field_src.node_offset.x };
2110
2111 try sema.mod.errNoteNonLazy(default_value_src.toSrcLoc(decl), msg, "default value set here", .{});
2097 const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg;
2098 const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{
2099 .index = field_index,
2100 .range = .value,
2101 });
2102 try sema.mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{});
21122103 break :msg msg;
21132104 };
21142105 return sema.failWithOwnedErrorMsg(msg);
......@@ -2146,15 +2137,61 @@ fn addFieldErrNote(
21462137 comptime format: []const u8,
21472138 args: anytype,
21482139) !void {
2140 @setCold(true);
21492141 const mod = sema.mod;
21502142 const decl_index = container_ty.getOwnerDecl();
21512143 const decl = mod.declPtr(decl_index);
2152 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {
2153 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
2154 return error.AnalysisFail;
2144
2145 const field_src = blk: {
2146 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {
2147 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
2148 break :blk decl.srcLoc();
2149 };
2150
2151 const container_node = decl.relativeToNodeIndex(0);
2152 const node_tags = tree.nodes.items(.tag);
2153 var buffer: [2]std.zig.Ast.Node.Index = undefined;
2154 const container_decl = switch (node_tags[container_node]) {
2155 .root => tree.containerDeclRoot(),
2156 .container_decl,
2157 .container_decl_trailing,
2158 => tree.containerDecl(container_node),
2159 .container_decl_two,
2160 .container_decl_two_trailing,
2161 => tree.containerDeclTwo(&buffer, container_node),
2162 .container_decl_arg,
2163 .container_decl_arg_trailing,
2164 => tree.containerDeclArg(container_node),
2165 .tagged_union,
2166 .tagged_union_trailing,
2167 => tree.taggedUnion(container_node),
2168 .tagged_union_two,
2169 .tagged_union_two_trailing,
2170 => tree.taggedUnionTwo(&buffer, container_node),
2171 .tagged_union_enum_tag,
2172 .tagged_union_enum_tag_trailing,
2173 => tree.taggedUnionEnumTag(container_node),
2174 else => break :blk decl.srcLoc(),
2175 };
2176
2177 var it_index: usize = 0;
2178 for (container_decl.ast.members) |member_node| {
2179 switch (node_tags[member_node]) {
2180 .container_field_init,
2181 .container_field_align,
2182 .container_field,
2183 => {
2184 if (it_index == field_index) {
2185 break :blk decl.nodeOffsetSrcLoc(decl.nodeIndexToRelative(member_node));
2186 }
2187 it_index += 1;
2188 },
2189 else => continue,
2190 }
2191 }
2192 unreachable;
21552193 };
2156 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_index);
2157 try mod.errNoteNonLazy(field_src.toSrcLoc(decl), parent, format, args);
2194 try mod.errNoteNonLazy(field_src, parent, format, args);
21582195}
21592196
21602197fn errMsg(
......@@ -2868,7 +2905,7 @@ fn zirEnumDecl(
28682905 .inlining = null,
28692906 .is_comptime = true,
28702907 };
2871 defer assert(enum_block.instructions.items.len == 0); // should all be comptime instructions
2908 defer enum_block.instructions.deinit(sema.gpa);
28722909
28732910 if (body.len != 0) {
28742911 try sema.analyzeBody(&enum_block, body);
......@@ -2934,13 +2971,12 @@ fn zirEnumDecl(
29342971
29352972 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);
29362973 if (gop_field.found_existing) {
2937 const tree = try sema.getAstTree(block);
2938 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
2939 const other_tag_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_field.index);
2974 const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
2975 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_field.index }).lazy;
29402976 const msg = msg: {
29412977 const msg = try sema.errMsg(block, field_src, "duplicate enum field '{s}'", .{field_name});
29422978 errdefer msg.destroy(gpa);
2943 try sema.errNote(block, other_tag_src, msg, "other field here", .{});
2979 try sema.errNote(block, other_field_src, msg, "other field here", .{});
29442980 break :msg msg;
29452981 };
29462982 return sema.failWithOwnedErrorMsg(msg);
......@@ -2949,10 +2985,18 @@ fn zirEnumDecl(
29492985 if (has_tag_value) {
29502986 const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
29512987 extra_index += 1;
2952 // TODO: if we need to report an error here, use a source location
2953 // that points to this default value expression rather than the struct.
2954 // But only resolve the source location if we need to emit a compile error.
2955 const tag_val = (try sema.resolveInstConst(block, src, tag_val_ref, "enum tag value must be comptime-known")).val;
2988 const tag_inst = try sema.resolveInst(tag_val_ref);
2989 const tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) {
2990 error.NeededSourceLocation => {
2991 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
2992 .index = field_i,
2993 .range = .value,
2994 }).lazy;
2995 _ = try sema.resolveConstValue(block, value_src, tag_inst, "enum tag value must be comptime-known");
2996 unreachable;
2997 },
2998 else => |e| return e,
2999 };
29563000 last_tag_val = tag_val;
29573001 const copied_tag_val = try tag_val.copy(decl_arena_allocator);
29583002 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
......@@ -2960,11 +3004,13 @@ fn zirEnumDecl(
29603004 .mod = mod,
29613005 });
29623006 if (gop_val.found_existing) {
2963 const tree = try sema.getAstTree(block);
2964 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
2965 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_val.index);
3007 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3008 .index = field_i,
3009 .range = .value,
3010 }).lazy;
3011 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy;
29663012 const msg = msg: {
2967 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)});
3013 const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)});
29683014 errdefer msg.destroy(gpa);
29693015 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
29703016 break :msg msg;
......@@ -2983,9 +3029,8 @@ fn zirEnumDecl(
29833029 .mod = mod,
29843030 });
29853031 if (gop_val.found_existing) {
2986 const tree = try sema.getAstTree(block);
2987 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
2988 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_val.index);
3032 const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
3033 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy;
29893034 const msg = msg: {
29903035 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)});
29913036 errdefer msg.destroy(gpa);
......@@ -3003,9 +3048,11 @@ fn zirEnumDecl(
30033048 }
30043049
30053050 if (!(try sema.intFitsInType(last_tag_val.?, enum_obj.tag_ty, null))) {
3006 const tree = try sema.getAstTree(block);
3007 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
3008 const msg = try sema.errMsg(block, field_src, "enumeration value '{}' too large for type '{}'", .{
3051 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3052 .index = field_i,
3053 .range = if (has_tag_value) .value else .name,
3054 }).lazy;
3055 const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{
30093056 last_tag_val.?.fmtValue(enum_obj.tag_ty, mod), enum_obj.tag_ty.fmt(mod),
30103057 });
30113058 return sema.failWithOwnedErrorMsg(msg);
......@@ -3319,8 +3366,6 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index
33193366 operand_ty.childType()
33203367 else
33213368 operand_ty;
3322 // TODO this should be validated in a more generic instruction that is
3323 // emitted for all ifs and whiles with an error union condition.
33243369 if (err_union_ty.zigTypeTag() != .ErrorUnion) return;
33253370 const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag();
33263371 if (payload_ty != .Void and payload_ty != .NoReturn) {
......@@ -5908,9 +5953,8 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
59085953pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {
59095954 const src = sema.src;
59105955
5911 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
5912 if (!backend_supports_error_return_tracing or !sema.mod.comp.bin_file.options.error_return_tracing)
5913 return .none;
5956 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return .none;
5957 if (!sema.mod.comp.bin_file.options.error_return_tracing) return .none;
59145958
59155959 if (block.is_comptime)
59165960 return .none;
......@@ -6148,8 +6192,7 @@ fn zirCall(
61486192 if (sema.owner_func == null or !sema.owner_func.?.calls_or_awaits_errorable_fn)
61496193 input_is_error = false; // input was an error type, but no errorable fn's were actually called
61506194
6151 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
6152 if (backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing and
6195 if (sema.mod.backendSupportsFeature(.error_return_trace) and sema.mod.comp.bin_file.options.error_return_tracing and
61536196 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))
61546197 {
61556198 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {
......@@ -7183,6 +7226,7 @@ fn instantiateGenericCall(
71837226 return err;
71847227 },
71857228 else => {
7229 assert(mod.monomorphed_funcs.remove(new_module_func));
71867230 {
71877231 errdefer new_decl_arena.deinit();
71887232 try new_decl.finalizeNewArena(&new_decl_arena);
......@@ -7936,11 +7980,8 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
79367980
79377981 try sema.requireRuntimeBlock(block, src, operand_src);
79387982 const result = try block.addTyOp(.intcast, dest_ty, operand);
7939 if (block.wantSafety() and
7940 !dest_ty.isNonexhaustiveEnum() and
7941 // TODO instead of "use_llvm", check a different condition so that backends
7942 // can advertise themselves as supporting these extra AIR instructions for safety.
7943 sema.mod.comp.bin_file.options.use_llvm)
7983 if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum() and
7984 sema.mod.backendSupportsFeature(.is_named_enum_value))
79447985 {
79457986 const ok = try block.addUnOp(.is_named_enum_value, result);
79467987 try sema.addSafetyCheck(block, ok, .invalid_enum_value);
......@@ -10658,8 +10699,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1065810699 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
1065910700 }
1066010701
10661 const backend_supports_is_named_enum = sema.mod.comp.bin_file.options.use_llvm;
10662
1066310702 if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) {
1066410703 if (empty_enum) {
1066510704 return Air.Inst.Ref.void_value;
......@@ -10670,7 +10709,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1067010709 if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) {
1067110710 return Air.Inst.Ref.unreachable_value;
1067210711 }
10673 if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and
10712 if (sema.mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and
1067410713 (!operand_ty.isNonexhaustiveEnum() or union_originally))
1067510714 {
1067610715 try sema.zirDbgStmt(block, cond_dbg_node_index);
......@@ -11140,7 +11179,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1114011179 case_block.wip_capture_scope = wip_captures.scope;
1114111180 case_block.inline_case_capture = .none;
1114211181
11143 if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and
11182 if (sema.mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and
1114411183 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))
1114511184 {
1114611185 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
......@@ -11453,10 +11492,7 @@ fn validateSwitchNoRange(
1145311492}
1145411493
1145511494fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, operand: Air.Inst.Ref) !bool {
11456 const this_feature_is_implemented_in_the_backend =
11457 sema.mod.comp.bin_file.options.use_llvm;
11458
11459 if (!this_feature_is_implemented_in_the_backend) return false;
11495 if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) return false;
1146011496
1146111497 const tags = sema.code.instructions.items(.tag);
1146211498 for (body) |inst| {
......@@ -16970,20 +17006,17 @@ fn retWithErrTracing(
1697017006}
1697117007
1697217008fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
16973 // TODO implement this feature in all the backends and then delete this check.
16974 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
17009 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return false;
1697517010
1697617011 return fn_ret_ty.isError() and
16977 sema.mod.comp.bin_file.options.error_return_tracing and
16978 backend_supports_error_return_tracing;
17012 sema.mod.comp.bin_file.options.error_return_tracing;
1697917013}
1698017014
1698117015fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
1698217016 const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index;
1698317017
16984 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
16985 const ok = backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing;
16986 if (!ok) return;
17018 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
17019 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;
1698717020
1698817021 // This is only relevant at runtime.
1698917022 if (block.is_comptime or block.is_typeof) return;
......@@ -17005,11 +17038,9 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1700517038 // This is only relevant at runtime.
1700617039 if (start_block.is_comptime or start_block.is_typeof) return;
1700717040
17008 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
17009 const ok = sema.owner_func.?.calls_or_awaits_errorable_fn and
17010 sema.mod.comp.bin_file.options.error_return_tracing and
17011 backend_supports_error_return_tracing;
17012 if (!ok) return;
17041 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
17042 if (!sema.owner_func.?.calls_or_awaits_errorable_fn) return;
17043 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;
1701317044
1701417045 const tracy = trace(@src());
1701517046 defer tracy.end();
......@@ -17988,14 +18019,10 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1798818019 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
1798918020 const opt_ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty);
1799018021
17991 // TODO implement this feature in all the backends and then delete this check.
17992 const backend_supports_error_return_tracing =
17993 sema.mod.comp.bin_file.options.use_llvm;
17994
1799518022 if (sema.owner_func != null and
1799618023 sema.owner_func.?.calls_or_awaits_errorable_fn and
1799718024 sema.mod.comp.bin_file.options.error_return_tracing and
17998 backend_supports_error_return_tracing)
18025 sema.mod.backendSupportsFeature(.error_return_trace))
1799918026 {
1800018027 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
1800118028 }
......@@ -18175,7 +18202,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1817518202 return sema.addStrLit(block, field_name);
1817618203 }
1817718204 try sema.requireRuntimeBlock(block, src, operand_src);
18178 if (block.wantSafety() and sema.mod.comp.bin_file.options.use_llvm) {
18205 if (block.wantSafety() and sema.mod.backendSupportsFeature(.is_named_enum_value)) {
1817918206 const ok = try block.addUnOp(.is_named_enum_value, casted_operand);
1818018207 try sema.addSafetyCheck(block, ok, .invalid_enum_value);
1818118208 }
......@@ -19469,7 +19496,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1946919496 }
1947019497
1947119498 try sema.requireRuntimeBlock(block, src, operand_src);
19472 if (block.wantSafety() and !dest_ty.isAnyError() and sema.mod.comp.bin_file.options.use_llvm) {
19499 if (block.wantSafety() and !dest_ty.isAnyError() and sema.mod.backendSupportsFeature(.error_set_has_value)) {
1947319500 const err_int_inst = try block.addBitCast(Type.err_int, operand);
1947419501 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
1947519502 try sema.addSafetyCheck(block, ok, .invalid_error_code);
......@@ -21596,7 +21623,7 @@ fn zirVarExtended(
2159621623 .owner_decl = sema.owner_decl_index,
2159721624 .init = init_val,
2159821625 .is_extern = small.is_extern,
21599 .is_mutable = true, // TODO get rid of this unused field
21626 .is_mutable = true,
2160021627 .is_threadlocal = small.is_threadlocal,
2160121628 .is_weak_linkage = false,
2160221629 .lib_name = null,
......@@ -22075,7 +22102,7 @@ fn zirBuiltinExtern(
2207522102 .owner_decl = sema.owner_decl_index,
2207622103 .init = Value.initTag(.unreachable_value),
2207722104 .is_extern = true,
22078 .is_mutable = false, // TODO get rid of this unused field
22105 .is_mutable = false,
2207922106 .is_threadlocal = options.is_thread_local,
2208022107 .is_weak_linkage = options.linkage == .Weak,
2208122108 .lib_name = null,
......@@ -22658,11 +22685,7 @@ fn panicWithMsg(
2265822685 const mod = sema.mod;
2265922686 const arena = sema.arena;
2266022687
22661 const this_feature_is_implemented_in_the_backend =
22662 mod.comp.bin_file.options.target.ofmt == .c or
22663 mod.comp.bin_file.options.use_llvm;
22664 if (!this_feature_is_implemented_in_the_backend) {
22665 // TODO implement this feature in all the backends and then delete this branch
22688 if (!mod.backendSupportsFeature(.panic_fn)) {
2266622689 _ = try block.addNoOp(.breakpoint);
2266722690 _ = try block.addNoOp(.unreach);
2266822691 return;
......@@ -22711,11 +22734,7 @@ fn panicUnwrapError(
2271122734 defer fail_block.instructions.deinit(gpa);
2271222735
2271322736 {
22714 const this_feature_is_implemented_in_the_backend =
22715 sema.mod.comp.bin_file.options.use_llvm;
22716
22717 if (!this_feature_is_implemented_in_the_backend) {
22718 // TODO implement this feature in all the backends and then delete this branch
22737 if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) {
2271922738 _ = try fail_block.addNoOp(.breakpoint);
2272022739 _ = try fail_block.addNoOp(.unreach);
2272122740 } else {
......@@ -22841,18 +22860,12 @@ fn safetyCheckFormatted(
2284122860
2284222861 defer fail_block.instructions.deinit(gpa);
2284322862
22844 {
22845 const this_feature_is_implemented_in_the_backend =
22846 sema.mod.comp.bin_file.options.use_llvm;
22847
22848 if (!this_feature_is_implemented_in_the_backend) {
22849 // TODO implement this feature in all the backends and then delete this branch
22850 _ = try fail_block.addNoOp(.breakpoint);
22851 _ = try fail_block.addNoOp(.unreach);
22852 } else {
22853 const panic_fn = try sema.getBuiltin(func);
22854 _ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, args, null);
22855 }
22863 if (!sema.mod.backendSupportsFeature(.safety_check_formatted)) {
22864 _ = try fail_block.addNoOp(.breakpoint);
22865 _ = try fail_block.addNoOp(.unreach);
22866 } else {
22867 const panic_fn = try sema.getBuiltin(func);
22868 _ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, args, null);
2285622869 }
2285722870 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
2285822871}
......@@ -24517,7 +24530,7 @@ fn coerceExtra(
2451724530 return block.addBitCast(dest_ty, inst);
2451824531 }
2451924532
24520 const is_undef = if (maybe_inst_val) |val| val.isUndef() else false;
24533 const is_undef = inst_ty.zigTypeTag() == .Undefined;
2452124534
2452224535 switch (dest_ty.zigTypeTag()) {
2452324536 .Optional => optional: {
......@@ -30662,14 +30675,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3066230675 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
3066330676 if (gop.found_existing) {
3066430677 const msg = msg: {
30665 const tree = try sema.getAstTree(&block_scope);
30666 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
30678 const field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
3066730679 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name});
3066830680 errdefer msg.destroy(gpa);
3066930681
3067030682 const prev_field_index = struct_obj.fields.getIndex(field_name).?;
30671 const prev_field_src = enumFieldSrcLoc(decl, tree.*, 0, prev_field_index);
30672 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});
30683 const prev_field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index });
30684 try sema.mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
3067330685 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});
3067430686 break :msg msg;
3067530687 };
......@@ -30699,34 +30711,51 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3069930711 // so that init values may depend on type layout.
3070030712 const bodies_index = extra_index;
3070130713
30702 for (fields) |zir_field, i| {
30703 // TODO emit compile errors for invalid field types
30704 // such as arrays and pointers inside packed structs.
30714 for (fields) |zir_field, field_i| {
3070530715 const field_ty: Type = ty: {
3070630716 if (zir_field.type_ref != .none) {
30707 // TODO: if we need to report an error here, use a source location
30708 // that points to this type expression rather than the struct.
30709 // But only resolve the source location if we need to emit a compile error.
30710 break :ty try sema.resolveType(&block_scope, src, zir_field.type_ref);
30717 break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) {
30718 error.NeededSourceLocation => {
30719 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30720 .index = field_i,
30721 .range = .type,
30722 }).lazy;
30723 _ = try sema.resolveType(&block_scope, ty_src, zir_field.type_ref);
30724 unreachable;
30725 },
30726 else => |e| return e,
30727 };
3071130728 }
3071230729 assert(zir_field.type_body_len != 0);
3071330730 const body = zir.extra[extra_index..][0..zir_field.type_body_len];
3071430731 extra_index += body.len;
3071530732 const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
30716 break :ty try sema.analyzeAsType(&block_scope, src, ty_ref);
30733 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {
30734 error.NeededSourceLocation => {
30735 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30736 .index = field_i,
30737 .range = .type,
30738 }).lazy;
30739 _ = try sema.analyzeAsType(&block_scope, ty_src, ty_ref);
30740 unreachable;
30741 },
30742 else => |e| return e,
30743 };
3071730744 };
3071830745 if (field_ty.tag() == .generic_poison) {
3071930746 return error.GenericPoison;
3072030747 }
3072130748
30722 const field = &struct_obj.fields.values()[i];
30749 const field = &struct_obj.fields.values()[field_i];
3072330750 field.ty = try field_ty.copy(decl_arena_allocator);
3072430751
3072530752 if (field_ty.zigTypeTag() == .Opaque) {
3072630753 const msg = msg: {
30727 const tree = try sema.getAstTree(&block_scope);
30728 const field_src = enumFieldSrcLoc(decl, tree.*, 0, i);
30729 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
30754 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30755 .index = field_i,
30756 .range = .type,
30757 }).lazy;
30758 const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
3073030759 errdefer msg.destroy(sema.gpa);
3073130760
3073230761 try sema.addDeclaredHereNote(msg, field_ty);
......@@ -30736,9 +30765,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3073630765 }
3073730766 if (field_ty.zigTypeTag() == .NoReturn) {
3073830767 const msg = msg: {
30739 const tree = try sema.getAstTree(&block_scope);
30740 const field_src = enumFieldSrcLoc(decl, tree.*, 0, i);
30741 const msg = try sema.errMsg(&block_scope, field_src, "struct fields cannot be 'noreturn'", .{});
30768 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30769 .index = field_i,
30770 .range = .type,
30771 }).lazy;
30772 const msg = try sema.errMsg(&block_scope, ty_src, "struct fields cannot be 'noreturn'", .{});
3074230773 errdefer msg.destroy(sema.gpa);
3074330774
3074430775 try sema.addDeclaredHereNote(msg, field_ty);
......@@ -30748,12 +30779,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3074830779 }
3074930780 if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) {
3075030781 const msg = msg: {
30751 const tree = try sema.getAstTree(&block_scope);
30752 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);
30753 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
30782 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30783 .index = field_i,
30784 .range = .type,
30785 });
30786 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
3075430787 errdefer msg.destroy(sema.gpa);
3075530788
30756 try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .struct_field);
30789 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field);
3075730790
3075830791 try sema.addDeclaredHereNote(msg, field.ty);
3075930792 break :msg msg;
......@@ -30761,12 +30794,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3076130794 return sema.failWithOwnedErrorMsg(msg);
3076230795 } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
3076330796 const msg = msg: {
30764 const tree = try sema.getAstTree(&block_scope);
30765 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);
30766 const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
30797 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30798 .index = field_i,
30799 .range = .type,
30800 });
30801 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
3076730802 errdefer msg.destroy(sema.gpa);
3076830803
30769 try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty);
30804 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty);
3077030805
3077130806 try sema.addDeclaredHereNote(msg, field.ty);
3077230807 break :msg msg;
......@@ -30778,7 +30813,17 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3077830813 const body = zir.extra[extra_index..][0..zir_field.align_body_len];
3077930814 extra_index += body.len;
3078030815 const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
30781 field.abi_align = try sema.analyzeAsAlign(&block_scope, src, align_ref);
30816 field.abi_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
30817 error.NeededSourceLocation => {
30818 const align_src = struct_obj.fieldSrcLoc(sema.mod, .{
30819 .index = field_i,
30820 .range = .alignment,
30821 }).lazy;
30822 _ = try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
30823 unreachable;
30824 },
30825 else => |e| return e,
30826 };
3078230827 }
3078330828
3078430829 extra_index += zir_field.init_body_len;
......@@ -30788,26 +30833,30 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3078830833
3078930834 if (any_inits) {
3079030835 extra_index = bodies_index;
30791 for (fields) |zir_field, i| {
30836 for (fields) |zir_field, field_i| {
3079230837 extra_index += zir_field.type_body_len;
3079330838 extra_index += zir_field.align_body_len;
3079430839 if (zir_field.init_body_len > 0) {
3079530840 const body = zir.extra[extra_index..][0..zir_field.init_body_len];
3079630841 extra_index += body.len;
3079730842 const init = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
30798 const field = &struct_obj.fields.values()[i];
30843 const field = &struct_obj.fields.values()[field_i];
3079930844 const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {
3080030845 error.NeededSourceLocation => {
30801 const tree = try sema.getAstTree(&block_scope);
30802 const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);
30846 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{
30847 .index = field_i,
30848 .range = .value,
30849 }).lazy;
3080330850 _ = try sema.coerce(&block_scope, field.ty, init, init_src);
3080430851 unreachable;
3080530852 },
3080630853 else => |e| return e,
3080730854 };
3080830855 const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
30809 const tree = try sema.getAstTree(&block_scope);
30810 const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);
30856 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{
30857 .index = field_i,
30858 .range = .value,
30859 }).lazy;
3081130860 return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known");
3081230861 };
3081330862 field.default_val = try default_val.copy(decl_arena_allocator);
......@@ -31023,9 +31072,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3102331072
3102431073 if (enum_value_map) |map| {
3102531074 const copied_val = if (tag_ref != .none) blk: {
31026 const tag_src = src; // TODO better source location
31027 const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, tag_src);
31028 const val = try sema.resolveConstValue(&block_scope, tag_src, coerced, "enum tag value must be comptime-known");
31075 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {
31076 error.NeededSourceLocation => {
31077 const val_src = union_obj.fieldSrcLoc(sema.mod, .{
31078 .index = field_i,
31079 .range = .value,
31080 }).lazy;
31081 _ = try sema.semaUnionFieldVal(&block_scope, val_src, int_tag_ty, tag_ref);
31082 unreachable;
31083 },
31084 else => |e| return e,
31085 };
3102931086 last_tag_val = val;
3103031087
3103131088 // This puts the memory into the union arena, not the enum arena, but
......@@ -31045,9 +31102,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3104531102 .mod = mod,
3104631103 });
3104731104 if (gop.found_existing) {
31048 const tree = try sema.getAstTree(&block_scope);
31049 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, field_i);
31050 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, gop.index);
31105 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
31106 const other_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = gop.index }).lazy;
3105131107 const msg = msg: {
3105231108 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});
3105331109 errdefer msg.destroy(gpa);
......@@ -31069,10 +31125,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3106931125 else if (field_type_ref == .none)
3107031126 Type.initTag(.noreturn)
3107131127 else
31072 // TODO: if we need to report an error here, use a source location
31073 // that points to this type expression rather than the union.
31074 // But only resolve the source location if we need to emit a compile error.
31075 try sema.resolveType(&block_scope, src, field_type_ref);
31128 sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) {
31129 error.NeededSourceLocation => {
31130 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31131 .index = field_i,
31132 .range = .type,
31133 }).lazy;
31134 _ = try sema.resolveType(&block_scope, ty_src, field_type_ref);
31135 unreachable;
31136 },
31137 else => |e| return e,
31138 };
3107631139
3107731140 if (field_ty.tag() == .generic_poison) {
3107831141 return error.GenericPoison;
......@@ -31081,13 +31144,12 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3108131144 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
3108231145 if (gop.found_existing) {
3108331146 const msg = msg: {
31084 const tree = try sema.getAstTree(&block_scope);
31085 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
31147 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
3108631148 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name});
3108731149 errdefer msg.destroy(gpa);
3108831150
3108931151 const prev_field_index = union_obj.fields.getIndex(field_name).?;
31090 const prev_field_src = enumFieldSrcLoc(decl, tree.*, 0, prev_field_index);
31152 const prev_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index }).lazy;
3109131153 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});
3109231154 try sema.errNote(&block_scope, src, msg, "union declared here", .{});
3109331155 break :msg msg;
......@@ -31099,9 +31161,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3109931161 const enum_has_field = names.orderedRemove(field_name);
3110031162 if (!enum_has_field) {
3110131163 const msg = msg: {
31102 const tree = try sema.getAstTree(&block_scope);
31103 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
31104 const msg = try sema.errMsg(&block_scope, field_src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) });
31164 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31165 .index = field_i,
31166 .range = .type,
31167 }).lazy;
31168 const msg = try sema.errMsg(&block_scope, ty_src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) });
3110531169 errdefer msg.destroy(sema.gpa);
3110631170 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
3110731171 break :msg msg;
......@@ -31112,9 +31176,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3111231176
3111331177 if (field_ty.zigTypeTag() == .Opaque) {
3111431178 const msg = msg: {
31115 const tree = try sema.getAstTree(&block_scope);
31116 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
31117 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
31179 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31180 .index = field_i,
31181 .range = .type,
31182 }).lazy;
31183 const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
3111831184 errdefer msg.destroy(sema.gpa);
3111931185
3112031186 try sema.addDeclaredHereNote(msg, field_ty);
......@@ -31124,12 +31190,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3112431190 }
3112531191 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {
3112631192 const msg = msg: {
31127 const tree = try sema.getAstTree(&block_scope);
31128 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
31129 const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
31193 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31194 .index = field_i,
31195 .range = .type,
31196 });
31197 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
3113031198 errdefer msg.destroy(sema.gpa);
3113131199
31132 try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field);
31200 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field);
3113331201
3113431202 try sema.addDeclaredHereNote(msg, field_ty);
3113531203 break :msg msg;
......@@ -31137,12 +31205,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3113731205 return sema.failWithOwnedErrorMsg(msg);
3113831206 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
3113931207 const msg = msg: {
31140 const tree = try sema.getAstTree(&block_scope);
31141 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
31142 const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
31208 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31209 .index = field_i,
31210 .range = .type,
31211 });
31212 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
3114331213 errdefer msg.destroy(sema.gpa);
3114431214
31145 try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty);
31215 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
3114631216
3114731217 try sema.addDeclaredHereNote(msg, field_ty);
3114831218 break :msg msg;
......@@ -31156,10 +31226,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3115631226 };
3115731227
3115831228 if (align_ref != .none) {
31159 // TODO: if we need to report an error here, use a source location
31160 // that points to this alignment expression rather than the struct.
31161 // But only resolve the source location if we need to emit a compile error.
31162 gop.value_ptr.abi_align = try sema.resolveAlign(&block_scope, src, align_ref);
31229 gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
31230 error.NeededSourceLocation => {
31231 const align_src = union_obj.fieldSrcLoc(sema.mod, .{
31232 .index = field_i,
31233 .range = .alignment,
31234 }).lazy;
31235 _ = try sema.resolveAlign(&block_scope, align_src, align_ref);
31236 unreachable;
31237 },
31238 else => |e| return e,
31239 };
3116331240 } else {
3116431241 gop.value_ptr.abi_align = 0;
3116531242 }
......@@ -31184,6 +31261,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3118431261 }
3118531262}
3118631263
31264fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Type, tag_ref: Air.Inst.Ref) CompileError!Value {
31265 const coerced = try sema.coerce(block, int_tag_ty, tag_ref, src);
31266 return sema.resolveConstValue(block, src, coerced, "enum tag value must be comptime-known");
31267}
31268
3118731269fn generateUnionTagTypeNumbered(
3118831270 sema: *Sema,
3118931271 block: *Block,
......@@ -31607,102 +31689,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3160731689 }
3160831690}
3160931691
31610fn getAstTree(sema: *Sema, block: *Block) CompileError!*const std.zig.Ast {
31611 return block.namespace.file_scope.getTree(sema.gpa) catch |err| {
31612 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
31613 return error.AnalysisFail;
31614 };
31615}
31616
31617fn enumFieldSrcLoc(
31618 decl: *Decl,
31619 tree: std.zig.Ast,
31620 node_offset: i32,
31621 field_index: usize,
31622) LazySrcLoc {
31623 @setCold(true);
31624 const field_node = containerFieldNode(decl, tree, node_offset, field_index) orelse
31625 return LazySrcLoc.nodeOffset(0);
31626 return decl.nodeSrcLoc(field_node);
31627}
31628
31629fn containerFieldInitSrcLoc(
31630 decl: *Decl,
31631 tree: std.zig.Ast,
31632 node_offset: i32,
31633 field_index: usize,
31634) LazySrcLoc {
31635 @setCold(true);
31636 const node_tags = tree.nodes.items(.tag);
31637 const field_node = containerFieldNode(decl, tree, node_offset, field_index) orelse
31638 return LazySrcLoc.nodeOffset(0);
31639 const node_data = tree.nodes.items(.data)[field_node];
31640
31641 const init_node = switch (node_tags[field_node]) {
31642 .container_field_init => node_data.rhs,
31643 .container_field => blk: {
31644 const extra_data = tree.extraData(node_data.rhs, std.zig.Ast.Node.ContainerField);
31645 break :blk extra_data.value_expr;
31646 },
31647 else => unreachable,
31648 };
31649
31650 return decl.nodeSrcLoc(init_node);
31651}
31652
31653fn containerFieldNode(
31654 decl: *Decl,
31655 tree: std.zig.Ast,
31656 node_offset: i32,
31657 field_index: usize,
31658) ?std.zig.Ast.Node.Index {
31659 @setCold(true);
31660 const enum_node = decl.relativeToNodeIndex(node_offset);
31661 const node_tags = tree.nodes.items(.tag);
31662 var buffer: [2]std.zig.Ast.Node.Index = undefined;
31663 const container_decl = switch (node_tags[enum_node]) {
31664 .root => tree.containerDeclRoot(),
31665
31666 .container_decl,
31667 .container_decl_trailing,
31668 => tree.containerDecl(enum_node),
31669
31670 .container_decl_two,
31671 .container_decl_two_trailing,
31672 => tree.containerDeclTwo(&buffer, enum_node),
31673
31674 .container_decl_arg,
31675 .container_decl_arg_trailing,
31676 => tree.containerDeclArg(enum_node),
31677
31678 .tagged_union,
31679 .tagged_union_trailing,
31680 => tree.taggedUnion(enum_node),
31681 .tagged_union_two,
31682 .tagged_union_two_trailing,
31683 => tree.taggedUnionTwo(&buffer, enum_node),
31684 .tagged_union_enum_tag,
31685 .tagged_union_enum_tag_trailing,
31686 => tree.taggedUnionEnumTag(enum_node),
31687
31688 else => return null,
31689 };
31690 var it_index: usize = 0;
31691 for (container_decl.ast.members) |member_node| {
31692 switch (node_tags[member_node]) {
31693 .container_field_init,
31694 .container_field_align,
31695 .container_field,
31696 => {
31697 if (it_index == field_index) return member_node;
31698 it_index += 1;
31699 },
31700
31701 else => continue,
31702 }
31703 } else unreachable;
31704}
31705
3170631692/// Returns the type of the AIR instruction.
3170731693fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {
3170831694 return sema.getTmpAir().typeOf(inst);
......@@ -31792,14 +31778,6 @@ fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {
3179231778 return sema.addConstant(ty, try Value.Tag.int_u64.create(sema.arena, int));
3179331779}
3179431780
31795fn addBool(sema: *Sema, ty: Type, boolean: bool) CompileError!Air.Inst.Ref {
31796 return switch (ty.zigTypeTag()) {
31797 .Vector => sema.addConstant(ty, try Value.Tag.repeated.create(sema.arena, Value.makeBool(boolean))),
31798 .Bool => try sema.resolveInst(if (boolean) .bool_true else .bool_false),
31799 else => unreachable,
31800 };
31801}
31802
3180331781fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {
3180431782 return sema.addConstant(ty, Value.undef);
3180531783}
......@@ -32443,27 +32421,6 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {
3244332421 return Value.fromBigInt(sema.arena, result_bigint.toConst());
3244432422}
3244532423
32446/// Supports both (vectors of) floats and ints; handles undefined scalars.
32447fn numberAddWrap(
32448 sema: *Sema,
32449 lhs: Value,
32450 rhs: Value,
32451 ty: Type,
32452) !Value {
32453 if (ty.zigTypeTag() == .Vector) {
32454 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
32455 for (result_data) |*scalar, i| {
32456 var lhs_buf: Value.ElemValueBuffer = undefined;
32457 var rhs_buf: Value.ElemValueBuffer = undefined;
32458 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
32459 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
32460 scalar.* = try sema.numberAddWrapScalar(lhs_elem, rhs_elem, ty.scalarType());
32461 }
32462 return Value.Tag.aggregate.create(sema.arena, result_data);
32463 }
32464 return sema.numberAddWrapScalar(lhs, rhs, ty);
32465}
32466
3246732424/// Supports both floats and ints; handles undefined.
3246832425fn numberAddWrapScalar(
3246932426 sema: *Sema,
......@@ -32522,27 +32479,6 @@ fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {
3252232479 return Value.fromBigInt(sema.arena, result_bigint.toConst());
3252332480}
3252432481
32525/// Supports both (vectors of) floats and ints; handles undefined scalars.
32526fn numberSubWrap(
32527 sema: *Sema,
32528 lhs: Value,
32529 rhs: Value,
32530 ty: Type,
32531) !Value {
32532 if (ty.zigTypeTag() == .Vector) {
32533 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
32534 for (result_data) |*scalar, i| {
32535 var lhs_buf: Value.ElemValueBuffer = undefined;
32536 var rhs_buf: Value.ElemValueBuffer = undefined;
32537 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
32538 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
32539 scalar.* = try sema.numberSubWrapScalar(lhs_elem, rhs_elem, ty.scalarType());
32540 }
32541 return Value.Tag.aggregate.create(sema.arena, result_data);
32542 }
32543 return sema.numberSubWrapScalar(lhs, rhs, ty);
32544}
32545
3254632482/// Supports both floats and ints; handles undefined.
3254732483fn numberSubWrapScalar(
3254832484 sema: *Sema,
src/Zir.zig+1-2
......@@ -100,8 +100,7 @@ pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {
100100
101101pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
102102 const raw_slice = code.extra[start..][0..len];
103 // TODO we should be able to directly `@ptrCast` the slice to the other slice type.
104 return @ptrCast([*]Inst.Ref, raw_slice.ptr)[0..len];
103 return @ptrCast([]Inst.Ref, raw_slice);
105104}
106105
107106pub fn hasCompileErrors(code: Zir) bool {
src/main.zig+1-2
......@@ -3454,8 +3454,7 @@ fn runOrTest(
34543454 } else if (watch) {
34553455 warn("process exited with code {d}", .{code});
34563456 } else {
3457 // TODO https://github.com/ziglang/zig/issues/6342
3458 process.exit(1);
3457 process.exit(code);
34593458 }
34603459 },
34613460 else => {
src/type.zig+2-44
......@@ -1236,7 +1236,7 @@ pub const Type = extern union {
12361236 // we can't hash these based on tags because they wouldn't match the expanded version.
12371237 .type_info => unreachable, // needed to resolve the type before now
12381238
1239 .bound_fn => unreachable, // TODO delete from the language
1239 .bound_fn => unreachable,
12401240 .var_args_param => unreachable, // can be any type
12411241 }
12421242 }
......@@ -3272,7 +3272,7 @@ pub const Type = extern union {
32723272 .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer
32733273 .function => unreachable, // represents machine code; not a pointer
32743274 .@"opaque" => unreachable, // no size available
3275 .bound_fn => unreachable, // TODO remove from the language
3275 .bound_fn => unreachable,
32763276 .noreturn => unreachable,
32773277 .inferred_alloc_const => unreachable,
32783278 .inferred_alloc_mut => unreachable,
......@@ -4088,47 +4088,6 @@ pub const Type = extern union {
40884088 }
40894089 }
40904090
4091 /// Returns if type can be used for a runtime variable
4092 pub fn isValidVarType(self: Type, is_extern: bool) bool {
4093 var ty = self;
4094 while (true) switch (ty.zigTypeTag()) {
4095 .Bool,
4096 .Int,
4097 .Float,
4098 .ErrorSet,
4099 .Enum,
4100 .Frame,
4101 .AnyFrame,
4102 => return true,
4103
4104 .Opaque => return is_extern,
4105 .ComptimeFloat,
4106 .ComptimeInt,
4107 .EnumLiteral,
4108 .NoReturn,
4109 .Type,
4110 .Void,
4111 .Undefined,
4112 .Null,
4113 => return false,
4114
4115 .Optional => {
4116 var buf: Payload.ElemType = undefined;
4117 return ty.optionalChild(&buf).isValidVarType(is_extern);
4118 },
4119 .Pointer, .Array, .Vector => ty = ty.elemType(),
4120 .ErrorUnion => ty = ty.errorUnionPayload(),
4121
4122 .Fn => @panic("TODO fn isValidVarType"),
4123 .Struct => {
4124 // TODO this is not always correct; introduce lazy value mechanism
4125 // and here we need to force a resolve of "type requires comptime".
4126 return true;
4127 },
4128 .Union => @panic("TODO union isValidVarType"),
4129 };
4130 }
4131
41324091 /// For *[N]T, returns [N]T.
41334092 /// For *T, returns T.
41344093 /// For [*]T, returns T.
......@@ -5434,7 +5393,6 @@ pub const Type = extern union {
54345393 }
54355394
54365395 /// Asserts the type is an enum or a union.
5437 /// TODO support unions
54385396 pub fn intTagType(ty: Type, buffer: *Payload.Bits) Type {
54395397 switch (ty.tag()) {
54405398 .enum_full, .enum_nonexhaustive => return ty.cast(Payload.EnumFull).?.data.tag_ty,
src/value.zig+1-3
......@@ -814,7 +814,6 @@ pub const Value = extern union {
814814 .float_80 => return out_stream.print("{}", .{val.castTag(.float_80).?.data}),
815815 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
816816 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
817 // TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that
818817 .eu_payload => {
819818 try out_stream.writeAll("(eu_payload) ");
820819 val = val.castTag(.eu_payload).?.data;
......@@ -989,8 +988,7 @@ pub const Value = extern union {
989988 switch (val.tag()) {
990989 .enum_field_index => {
991990 const field_index = val.castTag(.enum_field_index).?.data;
992 // TODO should `@intToEnum` do this `@intCast` for you?
993 return @intToEnum(E, @intCast(@typeInfo(E).Enum.tag_type, field_index));
991 return @intToEnum(E, field_index);
994992 },
995993 .the_only_possible_value => {
996994 const fields = std.meta.fields(E);
test/behavior/enum.zig+10
......@@ -1185,3 +1185,13 @@ test "runtime int to enum with one possible value" {
11851185 @compileError("test failed");
11861186 }
11871187}
1188
1189test "enum tag from a local variable" {
1190 const S = struct {
1191 fn Int(comptime Inner: type) type {
1192 return enum(Inner) { _ };
1193 }
1194 };
1195 const i = @intToEnum(S.Int(u32), 0);
1196 try std.testing.expect(@enumToInt(i) == 0);
1197}
test/cases/compile_errors/directly_embedding_opaque_type_in_struct_and_union.zig+2-2
......@@ -29,9 +29,9 @@ export fn d() void {
2929// backend=stage2
3030// target=native
3131//
32// :3:5: error: opaque types have unknown size and therefore cannot be directly embedded in structs
32// :3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs
3333// :1:11: note: opaque declared here
34// :7:5: error: opaque types have unknown size and therefore cannot be directly embedded in unions
34// :7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions
3535// :19:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs
3636// :18:22: note: opaque declared here
3737// :24:23: error: opaque types have unknown size and therefore cannot be directly embedded in structs
test/cases/compile_errors/enum_value_already_taken.zig+1-1
......@@ -14,5 +14,5 @@ export fn entry() void {
1414// backend=stage2
1515// target=native
1616//
17// :6:5: error: enum tag value 60 already taken
17// :6:9: error: enum tag value 60 already taken
1818// :4:5: note: other occurrence here
test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig+3-3
......@@ -39,7 +39,7 @@ export fn entry() void {
3939// backend=stage2
4040// target=native
4141//
42// :31:5: error: extern structs cannot contain fields of type 'tmp.E'
43// :31:5: note: enum tag type 'u9' is not extern compatible
44// :31:5: note: only integers with power of two bits are extern compatible
42// :31:8: error: extern structs cannot contain fields of type 'tmp.E'
43// :31:8: note: enum tag type 'u9' is not extern compatible
44// :31:8: note: only integers with power of two bits are extern compatible
4545// :1:15: note: enum declared here
test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig+3-3
......@@ -11,7 +11,7 @@ export fn entry() void {
1111// backend=stage2
1212// target=native
1313//
14// :3:5: error: extern structs cannot contain fields of type 'tmp.E'
15// :3:5: note: enum tag type 'u31' is not extern compatible
16// :3:5: note: only integers with power of two bits are extern compatible
14// :3:8: error: extern structs cannot contain fields of type 'tmp.E'
15// :3:8: note: enum tag type 'u31' is not extern compatible
16// :3:8: note: only integers with power of two bits are extern compatible
1717// :1:15: note: enum declared here
test/cases/compile_errors/file_level_struct_invalid_field_type.zig created+17
......@@ -0,0 +1,17 @@
1const Parser = @This();
2fn Chunk() type {
3 return struct {
4 const Self = @This();
5 };
6}
7parser_chunk: Chunk,
8
9comptime {
10 _ = @sizeOf(@This()) + 1;
11}
12
13// error
14// backend=stage2
15// target=native
16//
17// :7:15: error: expected type 'type', found 'fn() type'
test/cases/compile_errors/generic_function_instantiation_inherits_parent_branch_quota.zig created+30
......@@ -0,0 +1,30 @@
1pub export fn entry1() void {
2 @setEvalBranchQuota(1001);
3 // Return type evaluation should inherit both the
4 // parent's branch quota and count meaning
5 // at least 2002 backwards branches are required.
6 comptime var i = 0;
7 inline while (i < 1000) : (i += 1) {}
8 _ = simple(10);
9}
10pub export fn entry2() void {
11 @setEvalBranchQuota(2001);
12 comptime var i = 0;
13 inline while (i < 1000) : (i += 1) {}
14 _ = simple(10);
15}
16fn simple(comptime n: usize) Type(n) {
17 return n;
18}
19fn Type(comptime n: usize) type {
20 if (n <= 1) return usize;
21 return Type(n - 1);
22}
23
24// error
25// backend=stage2
26// target=native
27//
28// :21:16: error: evaluation exceeded 1001 backwards branches
29// :21:16: note: use @setEvalBranchQuota() to raise the branch limit from 1001
30// :16:34: note: called from here
test/cases/compile_errors/invalid_optional_type_in_extern_struct.zig+2-2
......@@ -7,5 +7,5 @@ export fn testf(fluff: *stroo) void { _ = fluff; }
77// backend=stage2
88// target=native
99//
10// :2:5: error: extern structs cannot contain fields of type '?[*c]u8'
11// :2:5: note: only pointer like optionals are extern compatible
10// :2:10: error: extern structs cannot contain fields of type '?[*c]u8'
11// :2:10: note: only pointer like optionals are extern compatible
test/cases/compile_errors/noreturn_struct_field.zig+1-1
......@@ -9,4 +9,4 @@ comptime {
99// backend=stage2
1010// target=native
1111//
12// :2:5: error: struct fields cannot be 'noreturn'
12// :2:8: error: struct fields cannot be 'noreturn'
test/cases/compile_errors/old_fn_ptr_in_extern_context.zig+3-3
......@@ -12,9 +12,9 @@ comptime {
1212// backend=stage2
1313// target=native
1414//
15// :2:5: error: extern structs cannot contain fields of type 'fn() callconv(.C) void'
16// :2:5: note: type has no guaranteed in-memory representation
17// :2:5: note: use '*const ' to make a function pointer type
15// :2:8: error: extern structs cannot contain fields of type 'fn() callconv(.C) void'
16// :2:8: note: type has no guaranteed in-memory representation
17// :2:8: note: use '*const ' to make a function pointer type
1818// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn() callconv(.C) void'
1919// :8:13: note: type has no guaranteed in-memory representation
2020// :8:13: note: use '*const ' to make a function pointer type
test/cases/compile_errors/only_untyped_undef_coerces_to_all_types.zig created+11
......@@ -0,0 +1,11 @@
1pub export fn entry() void {
2 const x: []u8 = undefined;
3 const y: f32 = x;
4 _ = y;
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :3:20: error: expected type 'f32', found '[]u8'
test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig+17-17
......@@ -70,22 +70,22 @@ export fn entry12() void {
7070// backend=llvm
7171// target=native
7272//
73// :3:9: error: packed structs cannot contain fields of type 'anyerror'
74// :3:9: note: type has no guaranteed in-memory representation
75// :8:9: error: packed structs cannot contain fields of type '[2]u24'
76// :8:9: note: type has no guaranteed in-memory representation
77// :13:9: error: packed structs cannot contain fields of type 'anyerror!u32'
78// :13:9: note: type has no guaranteed in-memory representation
79// :18:9: error: packed structs cannot contain fields of type 'tmp.S'
80// :18:9: note: only packed structs layout are allowed in packed types
73// :3:12: error: packed structs cannot contain fields of type 'anyerror'
74// :3:12: note: type has no guaranteed in-memory representation
75// :8:12: error: packed structs cannot contain fields of type '[2]u24'
76// :8:12: note: type has no guaranteed in-memory representation
77// :13:20: error: packed structs cannot contain fields of type 'anyerror!u32'
78// :13:20: note: type has no guaranteed in-memory representation
79// :18:12: error: packed structs cannot contain fields of type 'tmp.S'
80// :18:12: note: only packed structs layout are allowed in packed types
8181// :56:11: note: struct declared here
82// :23:9: error: packed structs cannot contain fields of type 'tmp.U'
83// :23:9: note: only packed unions layout are allowed in packed types
82// :23:12: error: packed structs cannot contain fields of type 'tmp.U'
83// :23:12: note: only packed unions layout are allowed in packed types
8484// :59:18: note: union declared here
85// :28:9: error: packed structs cannot contain fields of type '?anyerror'
86// :28:9: note: type has no guaranteed in-memory representation
87// :38:9: error: packed structs cannot contain fields of type 'fn() void'
88// :38:9: note: type has no guaranteed in-memory representation
89// :38:9: note: use '*const ' to make a function pointer type
90// :65:28: error: packed structs cannot contain fields of type '[]u8'
91// :65:28: note: slices have no guaranteed in-memory representation
85// :28:12: error: packed structs cannot contain fields of type '?anyerror'
86// :28:12: note: type has no guaranteed in-memory representation
87// :38:12: error: packed structs cannot contain fields of type 'fn() void'
88// :38:12: note: type has no guaranteed in-memory representation
89// :38:12: note: use '*const ' to make a function pointer type
90// :65:31: error: packed structs cannot contain fields of type '[]u8'
91// :65:31: note: slices have no guaranteed in-memory representation
test/cases/compile_errors/packed_union_with_automatic_layout_field.zig+2-2
......@@ -15,6 +15,6 @@ export fn entry() void {
1515// backend=stage2
1616// target=native
1717//
18// :6:5: error: packed unions cannot contain fields of type 'tmp.Foo'
19// :6:5: note: only packed structs layout are allowed in packed types
18// :6:8: error: packed unions cannot contain fields of type 'tmp.Foo'
19// :6:8: note: only packed structs layout are allowed in packed types
2020// :1:13: note: struct declared here
test/cases/compile_errors/union_enum_field_does_not_match_enum.zig+1-1
......@@ -18,5 +18,5 @@ export fn entry() void {
1818// backend=stage2
1919// target=native
2020//
21// :10:5: error: no field named 'D' in enum 'tmp.Letter'
21// :10:8: error: no field named 'D' in enum 'tmp.Letter'
2222// :1:16: note: enum declared here
test/cases/compile_errors/union_extra_field.zig+1-1
......@@ -16,5 +16,5 @@ export fn entry() usize {
1616// error
1717// target=native
1818//
19// :10:5: error: no field named 'd' in enum 'tmp.E'
19// :10:8: error: no field named 'd' in enum 'tmp.E'
2020// :1:11: note: enum declared here