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...@@ -2013,7 +2013,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2013 },2013 },
2014 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,2014 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2015 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,2015 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2016 .namespace => break,2016 .namespace, .enum_namespace => break,
2017 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,2017 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2018 .top => unreachable,2018 .top => unreachable,
2019 }2019 }
...@@ -2088,7 +2088,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2088,7 +2088,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2088 try parent_gz.addDefer(defer_scope.index, defer_scope.len);2088 try parent_gz.addDefer(defer_scope.index, defer_scope.len);
2089 },2089 },
2090 .defer_error => scope = scope.cast(Scope.Defer).?.parent,2090 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2091 .namespace => break,2091 .namespace, .enum_namespace => break,
2092 .top => unreachable,2092 .top => unreachable,
2093 }2093 }
2094 }2094 }
...@@ -2179,7 +2179,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke...@@ -2179,7 +2179,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke
2179 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,2179 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2180 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,2180 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2181 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,2181 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2182 .namespace => break,2182 .namespace, .enum_namespace => break,
2183 .top => unreachable,2183 .top => unreachable,
2184 }2184 }
2185 }2185 }
...@@ -2729,7 +2729,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct {...@@ -2729,7 +2729,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct {
2729 const have_err_payload = defer_scope.remapped_err_code != 0;2729 const have_err_payload = defer_scope.remapped_err_code != 0;
2730 need_err_code = need_err_code or have_err_payload;2730 need_err_code = need_err_code or have_err_payload;
2731 },2731 },
2732 .namespace => unreachable,2732 .namespace, .enum_namespace => unreachable,
2733 .top => unreachable,2733 .top => unreachable,
2734 }2734 }
2735 }2735 }
...@@ -2799,7 +2799,7 @@ fn genDefers(...@@ -2799,7 +2799,7 @@ fn genDefers(
2799 .normal_only => continue,2799 .normal_only => continue,
2800 }2800 }
2801 },2801 },
2802 .namespace => unreachable,2802 .namespace, .enum_namespace => unreachable,
2803 .top => unreachable,2803 .top => unreachable,
2804 }2804 }
2805 }2805 }
...@@ -2835,7 +2835,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v...@@ -2835,7 +2835,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v
2835 scope = s.parent;2835 scope = s.parent;
2836 },2836 },
2837 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,2837 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2838 .namespace => unreachable,2838 .namespace, .enum_namespace => unreachable,
2839 .top => unreachable,2839 .top => unreachable,
2840 }2840 }
2841 }2841 }
...@@ -4278,7 +4278,7 @@ fn testDecl(...@@ -4278,7 +4278,7 @@ fn testDecl(
4278 .local_val, .local_ptr => unreachable, // a test cannot be in a local scope4278 .local_val, .local_ptr => unreachable, // a test cannot be in a local scope
4279 .gen_zir => s = s.cast(GenZir).?.parent,4279 .gen_zir => s = s.cast(GenZir).?.parent,
4280 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,4280 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
4281 .namespace => {4281 .namespace, .enum_namespace => {
4282 const ns = s.cast(Scope.Namespace).?;4282 const ns = s.cast(Scope.Namespace).?;
4283 if (ns.decls.get(name_str_index)) |i| {4283 if (ns.decls.get(name_str_index)) |i| {
4284 if (found_already) |f| {4284 if (found_already) |f| {
...@@ -4963,6 +4963,7 @@ fn containerDecl(...@@ -4963,6 +4963,7 @@ fn containerDecl(
4963 defer block_scope.unstack();4963 defer block_scope.unstack();
49644964
4965 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);4965 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);
4966 namespace.base.tag = .enum_namespace;
49664967
4967 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)4968 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
4968 try comptimeExpr(&block_scope, &namespace.base, .{ .rl = .{ .ty = .type_type } }, container_decl.ast.arg)4969 try comptimeExpr(&block_scope, &namespace.base, .{ .rl = .{ .ty = .type_type } }, container_decl.ast.arg)
...@@ -4977,6 +4978,7 @@ fn containerDecl(...@@ -4977,6 +4978,7 @@ fn containerDecl(
4977 for (container_decl.ast.members) |member_node| {4978 for (container_decl.ast.members) |member_node| {
4978 if (member_node == counts.nonexhaustive_node)4979 if (member_node == counts.nonexhaustive_node)
4979 continue;4980 continue;
4981 namespace.base.tag = .namespace;
4980 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {4982 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
4981 .decl => continue,4983 .decl => continue,
4982 .field => |field| field,4984 .field => |field| field,
...@@ -5010,6 +5012,7 @@ fn containerDecl(...@@ -5010,6 +5012,7 @@ fn containerDecl(
5010 },5012 },
5011 );5013 );
5012 }5014 }
5015 namespace.base.tag = .enum_namespace;
5013 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);5016 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);
5014 wip_members.appendToField(@enumToInt(tag_value_inst));5017 wip_members.appendToField(@enumToInt(tag_value_inst));
5015 }5018 }
...@@ -7296,7 +7299,7 @@ fn localVarRef(...@@ -7296,7 +7299,7 @@ fn localVarRef(
7296 },7299 },
7297 .gen_zir => s = s.cast(GenZir).?.parent,7300 .gen_zir => s = s.cast(GenZir).?.parent,
7298 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,7301 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
7299 .namespace => {7302 .namespace, .enum_namespace => {
7300 const ns = s.cast(Scope.Namespace).?;7303 const ns = s.cast(Scope.Namespace).?;
7301 if (ns.decls.get(name_str_index)) |i| {7304 if (ns.decls.get(name_str_index)) |i| {
7302 if (found_already) |f| {7305 if (found_already) |f| {
...@@ -7308,7 +7311,7 @@ fn localVarRef(...@@ -7308,7 +7311,7 @@ fn localVarRef(
7308 // We found a match but must continue looking for ambiguous references to decls.7311 // We found a match but must continue looking for ambiguous references to decls.
7309 found_already = i;7312 found_already = i;
7310 }7313 }
7311 num_namespaces_out += 1;7314 if (s.tag == .namespace) num_namespaces_out += 1;
7312 capturing_namespace = ns;7315 capturing_namespace = ns;
7313 s = ns.parent;7316 s = ns.parent;
7314 },7317 },
...@@ -7935,7 +7938,7 @@ fn builtinCall(...@@ -7935,7 +7938,7 @@ fn builtinCall(
7935 },7938 },
7936 .gen_zir => s = s.cast(GenZir).?.parent,7939 .gen_zir => s = s.cast(GenZir).?.parent,
7937 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,7940 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
7938 .namespace => {7941 .namespace, .enum_namespace => {
7939 const ns = s.cast(Scope.Namespace).?;7942 const ns = s.cast(Scope.Namespace).?;
7940 if (ns.decls.get(decl_name)) |i| {7943 if (ns.decls.get(decl_name)) |i| {
7941 if (found_already) |f| {7944 if (found_already) |f| {
...@@ -10547,6 +10550,12 @@ const Scope = struct {...@@ -10547,6 +10550,12 @@ const Scope = struct {
10547 else => return null,10550 else => return null,
10548 }10551 }
10549 }10552 }
10553 if (T == Namespace) {
10554 switch (base.tag) {
10555 .namespace, .enum_namespace => return @fieldParentPtr(T, "base", base),
10556 else => return null,
10557 }
10558 }
10550 if (base.tag != T.base_tag)10559 if (base.tag != T.base_tag)
10551 return null;10560 return null;
1055210561
...@@ -10559,7 +10568,7 @@ const Scope = struct {...@@ -10559,7 +10568,7 @@ const Scope = struct {
10559 .local_val => base.cast(LocalVal).?.parent,10568 .local_val => base.cast(LocalVal).?.parent,
10560 .local_ptr => base.cast(LocalPtr).?.parent,10569 .local_ptr => base.cast(LocalPtr).?.parent,
10561 .defer_normal, .defer_error => base.cast(Defer).?.parent,10570 .defer_normal, .defer_error => base.cast(Defer).?.parent,
10562 .namespace => base.cast(Namespace).?.parent,10571 .namespace, .enum_namespace => base.cast(Namespace).?.parent,
10563 .top => null,10572 .top => null,
10564 };10573 };
10565 }10574 }
...@@ -10571,6 +10580,7 @@ const Scope = struct {...@@ -10571,6 +10580,7 @@ const Scope = struct {
10571 defer_normal,10580 defer_normal,
10572 defer_error,10581 defer_error,
10573 namespace,10582 namespace,
10583 enum_namespace,
10574 top,10584 top,
10575 };10585 };
1057610586
...@@ -12247,7 +12257,7 @@ fn detectLocalShadowing(...@@ -12247,7 +12257,7 @@ fn detectLocalShadowing(
12247 }12257 }
12248 s = local_ptr.parent;12258 s = local_ptr.parent;
12249 },12259 },
12250 .namespace => {12260 .namespace, .enum_namespace => {
12251 outer_scope = true;12261 outer_scope = true;
12252 const ns = s.cast(Scope.Namespace).?;12262 const ns = s.cast(Scope.Namespace).?;
12253 const decl_node = ns.decls.get(ident_name) orelse {12263 const decl_node = ns.decls.get(ident_name) orelse {
...@@ -12415,7 +12425,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -12415,7 +12425,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
12415 }12425 }
12416 s = local_ptr.parent;12426 s = local_ptr.parent;
12417 },12427 },
12418 .namespace => s = s.cast(Scope.Namespace).?.parent,12428 .namespace, .enum_namespace => s = s.cast(Scope.Namespace).?.parent,
12419 .gen_zir => s = s.cast(GenZir).?.parent,12429 .gen_zir => s = s.cast(GenZir).?.parent,
12420 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,12430 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
12421 .top => break,12431 .top => break,
src/Module.zig+66-9
...@@ -1194,6 +1194,49 @@ pub const EnumFull = struct {...@@ -1194,6 +1194,49 @@ pub const EnumFull = struct {
1194 .lazy = LazySrcLoc.nodeOffset(0),1194 .lazy = LazySrcLoc.nodeOffset(0),
1195 };1195 };
1196 }1196 }
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 }
1197};1240};
11981241
1199pub const Union = struct {1242pub const Union = struct {
...@@ -3519,14 +3562,6 @@ pub fn deinit(mod: *Module) void {...@@ -3519,14 +3562,6 @@ pub fn deinit(mod: *Module) void {
3519pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {3562pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3520 const gpa = mod.gpa;3563 const gpa = mod.gpa;
3521 {3564 {
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 }
3530 const decl = mod.declPtr(decl_index);3565 const decl = mod.declPtr(decl_index);
3531 log.debug("destroy {*} ({s})", .{ decl, decl.name });3566 log.debug("destroy {*} ({s})", .{ decl, decl.name });
3532 _ = mod.test_functions.swapRemove(decl_index);3567 _ = mod.test_functions.swapRemove(decl_index);
...@@ -6179,7 +6214,7 @@ pub const PeerTypeCandidateSrc = union(enum) {...@@ -6179,7 +6214,7 @@ pub const PeerTypeCandidateSrc = union(enum) {
61796214
6180const FieldSrcQuery = struct {6215const FieldSrcQuery = struct {
6181 index: usize,6216 index: usize,
6182 range: enum { name, type, value, alignment },6217 range: enum { name, type, value, alignment } = .name,
6183};6218};
61846219
6185fn queryFieldSrc(6220fn queryFieldSrc(
...@@ -6749,3 +6784,25 @@ pub fn getDeclExports(mod: Module, decl_index: Decl.Index) []const *Export {...@@ -6749,3 +6784,25 @@ pub fn getDeclExports(mod: Module, decl_index: Decl.Index) []const *Export {
6749 return &[0]*Export{};6784 return &[0]*Export{};
6750 }6785 }
6751}6786}
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(...@@ -1820,12 +1820,7 @@ fn analyzeAsType(
1820}1820}
18211821
1822pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void {1822pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void {
1823 const backend_supports_error_return_tracing =1823 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
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 }
18291824
1830 assert(!block.is_comptime);1825 assert(!block.is_comptime);
1831 var err_trace_block = block.makeSubBlock();1826 var err_trace_block = block.makeSubBlock();
...@@ -2099,16 +2094,12 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS...@@ -2099,16 +2094,12 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS
2099 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});2094 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});
2100 errdefer msg.destroy(sema.gpa);2095 errdefer msg.destroy(sema.gpa);
21012096
2102 const decl_index = container_ty.getOwnerDeclOrNull() orelse break :msg msg;2097 const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg;
2103 const decl = sema.mod.declPtr(decl_index);2098 const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{
2104 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {2099 .index = field_index,
2105 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});2100 .range = .value,
2106 return error.AnalysisFail;2101 });
2107 };2102 try sema.mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{});
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", .{});
2112 break :msg msg;2103 break :msg msg;
2113 };2104 };
2114 return sema.failWithOwnedErrorMsg(msg);2105 return sema.failWithOwnedErrorMsg(msg);
...@@ -2146,15 +2137,61 @@ fn addFieldErrNote(...@@ -2146,15 +2137,61 @@ fn addFieldErrNote(
2146 comptime format: []const u8,2137 comptime format: []const u8,
2147 args: anytype,2138 args: anytype,
2148) !void {2139) !void {
2140 @setCold(true);
2149 const mod = sema.mod;2141 const mod = sema.mod;
2150 const decl_index = container_ty.getOwnerDecl();2142 const decl_index = container_ty.getOwnerDecl();
2151 const decl = mod.declPtr(decl_index);2143 const decl = mod.declPtr(decl_index);
2152 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {2144
2153 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});2145 const field_src = blk: {
2154 return error.AnalysisFail;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;
2155 };2193 };
2156 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_index);2194 try mod.errNoteNonLazy(field_src, parent, format, args);
2157 try mod.errNoteNonLazy(field_src.toSrcLoc(decl), parent, format, args);
2158}2195}
21592196
2160fn errMsg(2197fn errMsg(
...@@ -2868,7 +2905,7 @@ fn zirEnumDecl(...@@ -2868,7 +2905,7 @@ fn zirEnumDecl(
2868 .inlining = null,2905 .inlining = null,
2869 .is_comptime = true,2906 .is_comptime = true,
2870 };2907 };
2871 defer assert(enum_block.instructions.items.len == 0); // should all be comptime instructions2908 defer enum_block.instructions.deinit(sema.gpa);
28722909
2873 if (body.len != 0) {2910 if (body.len != 0) {
2874 try sema.analyzeBody(&enum_block, body);2911 try sema.analyzeBody(&enum_block, body);
...@@ -2934,13 +2971,12 @@ fn zirEnumDecl(...@@ -2934,13 +2971,12 @@ fn zirEnumDecl(
29342971
2935 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);2972 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);
2936 if (gop_field.found_existing) {2973 if (gop_field.found_existing) {
2937 const tree = try sema.getAstTree(block);2974 const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
2938 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);2975 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_field.index }).lazy;
2939 const other_tag_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_field.index);
2940 const msg = msg: {2976 const msg = msg: {
2941 const msg = try sema.errMsg(block, field_src, "duplicate enum field '{s}'", .{field_name});2977 const msg = try sema.errMsg(block, field_src, "duplicate enum field '{s}'", .{field_name});
2942 errdefer msg.destroy(gpa);2978 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", .{});
2944 break :msg msg;2980 break :msg msg;
2945 };2981 };
2946 return sema.failWithOwnedErrorMsg(msg);2982 return sema.failWithOwnedErrorMsg(msg);
...@@ -2949,10 +2985,18 @@ fn zirEnumDecl(...@@ -2949,10 +2985,18 @@ fn zirEnumDecl(
2949 if (has_tag_value) {2985 if (has_tag_value) {
2950 const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);2986 const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2951 extra_index += 1;2987 extra_index += 1;
2952 // TODO: if we need to report an error here, use a source location2988 const tag_inst = try sema.resolveInst(tag_val_ref);
2953 // that points to this default value expression rather than the struct.2989 const tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) {
2954 // But only resolve the source location if we need to emit a compile error.2990 error.NeededSourceLocation => {
2955 const tag_val = (try sema.resolveInstConst(block, src, tag_val_ref, "enum tag value must be comptime-known")).val;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 };
2956 last_tag_val = tag_val;3000 last_tag_val = tag_val;
2957 const copied_tag_val = try tag_val.copy(decl_arena_allocator);3001 const copied_tag_val = try tag_val.copy(decl_arena_allocator);
2958 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{3002 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
...@@ -2960,11 +3004,13 @@ fn zirEnumDecl(...@@ -2960,11 +3004,13 @@ fn zirEnumDecl(
2960 .mod = mod,3004 .mod = mod,
2961 });3005 });
2962 if (gop_val.found_existing) {3006 if (gop_val.found_existing) {
2963 const tree = try sema.getAstTree(block);3007 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
2964 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);3008 .index = field_i,
2965 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_val.index);3009 .range = .value,
3010 }).lazy;
3011 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy;
2966 const msg = msg: {3012 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)});
2968 errdefer msg.destroy(gpa);3014 errdefer msg.destroy(gpa);
2969 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});3015 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
2970 break :msg msg;3016 break :msg msg;
...@@ -2983,9 +3029,8 @@ fn zirEnumDecl(...@@ -2983,9 +3029,8 @@ fn zirEnumDecl(
2983 .mod = mod,3029 .mod = mod,
2984 });3030 });
2985 if (gop_val.found_existing) {3031 if (gop_val.found_existing) {
2986 const tree = try sema.getAstTree(block);3032 const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
2987 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);3033 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy;
2988 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_val.index);
2989 const msg = msg: {3034 const msg = msg: {
2990 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)});3035 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)});
2991 errdefer msg.destroy(gpa);3036 errdefer msg.destroy(gpa);
...@@ -3003,9 +3048,11 @@ fn zirEnumDecl(...@@ -3003,9 +3048,11 @@ fn zirEnumDecl(
3003 }3048 }
30043049
3005 if (!(try sema.intFitsInType(last_tag_val.?, enum_obj.tag_ty, null))) {3050 if (!(try sema.intFitsInType(last_tag_val.?, enum_obj.tag_ty, null))) {
3006 const tree = try sema.getAstTree(block);3051 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3007 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);3052 .index = field_i,
3008 const msg = try sema.errMsg(block, field_src, "enumeration value '{}' too large for type '{}'", .{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 '{}'", .{
3009 last_tag_val.?.fmtValue(enum_obj.tag_ty, mod), enum_obj.tag_ty.fmt(mod),3056 last_tag_val.?.fmtValue(enum_obj.tag_ty, mod), enum_obj.tag_ty.fmt(mod),
3010 });3057 });
3011 return sema.failWithOwnedErrorMsg(msg);3058 return sema.failWithOwnedErrorMsg(msg);
...@@ -3319,8 +3366,6 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index...@@ -3319,8 +3366,6 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index
3319 operand_ty.childType()3366 operand_ty.childType()
3320 else3367 else
3321 operand_ty;3368 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.
3324 if (err_union_ty.zigTypeTag() != .ErrorUnion) return;3369 if (err_union_ty.zigTypeTag() != .ErrorUnion) return;
3325 const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag();3370 const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag();
3326 if (payload_ty != .Void and payload_ty != .NoReturn) {3371 if (payload_ty != .Void and payload_ty != .NoReturn) {
...@@ -5908,9 +5953,8 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {...@@ -5908,9 +5953,8 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
5908pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {5953pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {
5909 const src = sema.src;5954 const src = sema.src;
59105955
5911 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;5956 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return .none;
5912 if (!backend_supports_error_return_tracing or !sema.mod.comp.bin_file.options.error_return_tracing)5957 if (!sema.mod.comp.bin_file.options.error_return_tracing) return .none;
5913 return .none;
59145958
5915 if (block.is_comptime)5959 if (block.is_comptime)
5916 return .none;5960 return .none;
...@@ -6148,8 +6192,7 @@ fn zirCall(...@@ -6148,8 +6192,7 @@ fn zirCall(
6148 if (sema.owner_func == null or !sema.owner_func.?.calls_or_awaits_errorable_fn)6192 if (sema.owner_func == null or !sema.owner_func.?.calls_or_awaits_errorable_fn)
6149 input_is_error = false; // input was an error type, but no errorable fn's were actually called6193 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;6195 if (sema.mod.backendSupportsFeature(.error_return_trace) and sema.mod.comp.bin_file.options.error_return_tracing and
6152 if (backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing and
6153 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))6196 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))
6154 {6197 {
6155 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {6198 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {
...@@ -7183,6 +7226,7 @@ fn instantiateGenericCall(...@@ -7183,6 +7226,7 @@ fn instantiateGenericCall(
7183 return err;7226 return err;
7184 },7227 },
7185 else => {7228 else => {
7229 assert(mod.monomorphed_funcs.remove(new_module_func));
7186 {7230 {
7187 errdefer new_decl_arena.deinit();7231 errdefer new_decl_arena.deinit();
7188 try new_decl.finalizeNewArena(&new_decl_arena);7232 try new_decl.finalizeNewArena(&new_decl_arena);
...@@ -7936,11 +7980,8 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -7936,11 +7980,8 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
79367980
7937 try sema.requireRuntimeBlock(block, src, operand_src);7981 try sema.requireRuntimeBlock(block, src, operand_src);
7938 const result = try block.addTyOp(.intcast, dest_ty, operand);7982 const result = try block.addTyOp(.intcast, dest_ty, operand);
7939 if (block.wantSafety() and7983 if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum() and
7940 !dest_ty.isNonexhaustiveEnum() and7984 sema.mod.backendSupportsFeature(.is_named_enum_value))
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)
7944 {7985 {
7945 const ok = try block.addUnOp(.is_named_enum_value, result);7986 const ok = try block.addUnOp(.is_named_enum_value, result);
7946 try sema.addSafetyCheck(block, ok, .invalid_enum_value);7987 try sema.addSafetyCheck(block, ok, .invalid_enum_value);
...@@ -10658,8 +10699,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10658,8 +10699,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10658 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);10699 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
10659 }10700 }
1066010701
10661 const backend_supports_is_named_enum = sema.mod.comp.bin_file.options.use_llvm;
10662
10663 if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) {10702 if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) {
10664 if (empty_enum) {10703 if (empty_enum) {
10665 return Air.Inst.Ref.void_value;10704 return Air.Inst.Ref.void_value;
...@@ -10670,7 +10709,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10670,7 +10709,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10670 if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) {10709 if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) {
10671 return Air.Inst.Ref.unreachable_value;10710 return Air.Inst.Ref.unreachable_value;
10672 }10711 }
10673 if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and10712 if (sema.mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and
10674 (!operand_ty.isNonexhaustiveEnum() or union_originally))10713 (!operand_ty.isNonexhaustiveEnum() or union_originally))
10675 {10714 {
10676 try sema.zirDbgStmt(block, cond_dbg_node_index);10715 try sema.zirDbgStmt(block, cond_dbg_node_index);
...@@ -11140,7 +11179,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11140,7 +11179,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11140 case_block.wip_capture_scope = wip_captures.scope;11179 case_block.wip_capture_scope = wip_captures.scope;
11141 case_block.inline_case_capture = .none;11180 case_block.inline_case_capture = .none;
1114211181
11143 if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and11182 if (sema.mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and
11144 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))11183 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))
11145 {11184 {
11146 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);11185 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
...@@ -11453,10 +11492,7 @@ fn validateSwitchNoRange(...@@ -11453,10 +11492,7 @@ fn validateSwitchNoRange(
11453}11492}
1145411493
11455fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, operand: Air.Inst.Ref) !bool {11494fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, operand: Air.Inst.Ref) !bool {
11456 const this_feature_is_implemented_in_the_backend =11495 if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) return false;
11457 sema.mod.comp.bin_file.options.use_llvm;
11458
11459 if (!this_feature_is_implemented_in_the_backend) return false;
1146011496
11461 const tags = sema.code.instructions.items(.tag);11497 const tags = sema.code.instructions.items(.tag);
11462 for (body) |inst| {11498 for (body) |inst| {
...@@ -16970,20 +17006,17 @@ fn retWithErrTracing(...@@ -16970,20 +17006,17 @@ fn retWithErrTracing(
16970}17006}
1697117007
16972fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {17008fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
16973 // TODO implement this feature in all the backends and then delete this check.17009 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return false;
16974 const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
1697517010
16976 return fn_ret_ty.isError() and17011 return fn_ret_ty.isError() and
16977 sema.mod.comp.bin_file.options.error_return_tracing and17012 sema.mod.comp.bin_file.options.error_return_tracing;
16978 backend_supports_error_return_tracing;
16979}17013}
1698017014
16981fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {17015fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
16982 const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index;17016 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;17018 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
16985 const ok = backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing;17019 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;
16986 if (!ok) return;
1698717020
16988 // This is only relevant at runtime.17021 // This is only relevant at runtime.
16989 if (block.is_comptime or block.is_typeof) return;17022 if (block.is_comptime or block.is_typeof) return;
...@@ -17005,11 +17038,9 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -17005,11 +17038,9 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
17005 // This is only relevant at runtime.17038 // This is only relevant at runtime.
17006 if (start_block.is_comptime or start_block.is_typeof) return;17039 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;17041 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
17009 const ok = sema.owner_func.?.calls_or_awaits_errorable_fn and17042 if (!sema.owner_func.?.calls_or_awaits_errorable_fn) return;
17010 sema.mod.comp.bin_file.options.error_return_tracing and17043 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;
17011 backend_supports_error_return_tracing;
17012 if (!ok) return;
1701317044
17014 const tracy = trace(@src());17045 const tracy = trace(@src());
17015 defer tracy.end();17046 defer tracy.end();
...@@ -17988,14 +18019,10 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -17988,14 +18019,10 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
17988 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);18019 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
17989 const opt_ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty);18020 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
17995 if (sema.owner_func != null and18022 if (sema.owner_func != null and
17996 sema.owner_func.?.calls_or_awaits_errorable_fn and18023 sema.owner_func.?.calls_or_awaits_errorable_fn and
17997 sema.mod.comp.bin_file.options.error_return_tracing and18024 sema.mod.comp.bin_file.options.error_return_tracing and
17998 backend_supports_error_return_tracing)18025 sema.mod.backendSupportsFeature(.error_return_trace))
17999 {18026 {
18000 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);18027 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
18001 }18028 }
...@@ -18175,7 +18202,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -18175,7 +18202,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18175 return sema.addStrLit(block, field_name);18202 return sema.addStrLit(block, field_name);
18176 }18203 }
18177 try sema.requireRuntimeBlock(block, src, operand_src);18204 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)) {
18179 const ok = try block.addUnOp(.is_named_enum_value, casted_operand);18206 const ok = try block.addUnOp(.is_named_enum_value, casted_operand);
18180 try sema.addSafetyCheck(block, ok, .invalid_enum_value);18207 try sema.addSafetyCheck(block, ok, .invalid_enum_value);
18181 }18208 }
...@@ -19469,7 +19496,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -19469,7 +19496,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
19469 }19496 }
1947019497
19471 try sema.requireRuntimeBlock(block, src, operand_src);19498 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)) {
19473 const err_int_inst = try block.addBitCast(Type.err_int, operand);19500 const err_int_inst = try block.addBitCast(Type.err_int, operand);
19474 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);19501 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
19475 try sema.addSafetyCheck(block, ok, .invalid_error_code);19502 try sema.addSafetyCheck(block, ok, .invalid_error_code);
...@@ -21596,7 +21623,7 @@ fn zirVarExtended(...@@ -21596,7 +21623,7 @@ fn zirVarExtended(
21596 .owner_decl = sema.owner_decl_index,21623 .owner_decl = sema.owner_decl_index,
21597 .init = init_val,21624 .init = init_val,
21598 .is_extern = small.is_extern,21625 .is_extern = small.is_extern,
21599 .is_mutable = true, // TODO get rid of this unused field21626 .is_mutable = true,
21600 .is_threadlocal = small.is_threadlocal,21627 .is_threadlocal = small.is_threadlocal,
21601 .is_weak_linkage = false,21628 .is_weak_linkage = false,
21602 .lib_name = null,21629 .lib_name = null,
...@@ -22075,7 +22102,7 @@ fn zirBuiltinExtern(...@@ -22075,7 +22102,7 @@ fn zirBuiltinExtern(
22075 .owner_decl = sema.owner_decl_index,22102 .owner_decl = sema.owner_decl_index,
22076 .init = Value.initTag(.unreachable_value),22103 .init = Value.initTag(.unreachable_value),
22077 .is_extern = true,22104 .is_extern = true,
22078 .is_mutable = false, // TODO get rid of this unused field22105 .is_mutable = false,
22079 .is_threadlocal = options.is_thread_local,22106 .is_threadlocal = options.is_thread_local,
22080 .is_weak_linkage = options.linkage == .Weak,22107 .is_weak_linkage = options.linkage == .Weak,
22081 .lib_name = null,22108 .lib_name = null,
...@@ -22658,11 +22685,7 @@ fn panicWithMsg(...@@ -22658,11 +22685,7 @@ fn panicWithMsg(
22658 const mod = sema.mod;22685 const mod = sema.mod;
22659 const arena = sema.arena;22686 const arena = sema.arena;
2266022687
22661 const this_feature_is_implemented_in_the_backend =22688 if (!mod.backendSupportsFeature(.panic_fn)) {
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
22666 _ = try block.addNoOp(.breakpoint);22689 _ = try block.addNoOp(.breakpoint);
22667 _ = try block.addNoOp(.unreach);22690 _ = try block.addNoOp(.unreach);
22668 return;22691 return;
...@@ -22711,11 +22734,7 @@ fn panicUnwrapError(...@@ -22711,11 +22734,7 @@ fn panicUnwrapError(
22711 defer fail_block.instructions.deinit(gpa);22734 defer fail_block.instructions.deinit(gpa);
2271222735
22713 {22736 {
22714 const this_feature_is_implemented_in_the_backend =22737 if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) {
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
22719 _ = try fail_block.addNoOp(.breakpoint);22738 _ = try fail_block.addNoOp(.breakpoint);
22720 _ = try fail_block.addNoOp(.unreach);22739 _ = try fail_block.addNoOp(.unreach);
22721 } else {22740 } else {
...@@ -22841,18 +22860,12 @@ fn safetyCheckFormatted(...@@ -22841,18 +22860,12 @@ fn safetyCheckFormatted(
2284122860
22842 defer fail_block.instructions.deinit(gpa);22861 defer fail_block.instructions.deinit(gpa);
2284322862
22844 {22863 if (!sema.mod.backendSupportsFeature(.safety_check_formatted)) {
22845 const this_feature_is_implemented_in_the_backend =22864 _ = try fail_block.addNoOp(.breakpoint);
22846 sema.mod.comp.bin_file.options.use_llvm;22865 _ = try fail_block.addNoOp(.unreach);
2284722866 } else {
22848 if (!this_feature_is_implemented_in_the_backend) {22867 const panic_fn = try sema.getBuiltin(func);
22849 // TODO implement this feature in all the backends and then delete this branch22868 _ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, args, null);
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 }
22856 }22869 }
22857 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);22870 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
22858}22871}
...@@ -24517,7 +24530,7 @@ fn coerceExtra(...@@ -24517,7 +24530,7 @@ fn coerceExtra(
24517 return block.addBitCast(dest_ty, inst);24530 return block.addBitCast(dest_ty, inst);
24518 }24531 }
2451924532
24520 const is_undef = if (maybe_inst_val) |val| val.isUndef() else false;24533 const is_undef = inst_ty.zigTypeTag() == .Undefined;
2452124534
24522 switch (dest_ty.zigTypeTag()) {24535 switch (dest_ty.zigTypeTag()) {
24523 .Optional => optional: {24536 .Optional => optional: {
...@@ -30662,14 +30675,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30662,14 +30675,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30662 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);30675 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
30663 if (gop.found_existing) {30676 if (gop.found_existing) {
30664 const msg = msg: {30677 const msg = msg: {
30665 const tree = try sema.getAstTree(&block_scope);30678 const field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
30666 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
30667 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name});30679 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name});
30668 errdefer msg.destroy(gpa);30680 errdefer msg.destroy(gpa);
3066930681
30670 const prev_field_index = struct_obj.fields.getIndex(field_name).?;30682 const prev_field_index = struct_obj.fields.getIndex(field_name).?;
30671 const prev_field_src = enumFieldSrcLoc(decl, tree.*, 0, prev_field_index);30683 const prev_field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index });
30672 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});30684 try sema.mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
30673 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});30685 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});
30674 break :msg msg;30686 break :msg msg;
30675 };30687 };
...@@ -30699,34 +30711,51 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30699,34 +30711,51 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30699 // so that init values may depend on type layout.30711 // so that init values may depend on type layout.
30700 const bodies_index = extra_index;30712 const bodies_index = extra_index;
3070130713
30702 for (fields) |zir_field, i| {30714 for (fields) |zir_field, field_i| {
30703 // TODO emit compile errors for invalid field types
30704 // such as arrays and pointers inside packed structs.
30705 const field_ty: Type = ty: {30715 const field_ty: Type = ty: {
30706 if (zir_field.type_ref != .none) {30716 if (zir_field.type_ref != .none) {
30707 // TODO: if we need to report an error here, use a source location30717 break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) {
30708 // that points to this type expression rather than the struct.30718 error.NeededSourceLocation => {
30709 // But only resolve the source location if we need to emit a compile error.30719 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30710 break :ty try sema.resolveType(&block_scope, src, zir_field.type_ref);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 };
30711 }30728 }
30712 assert(zir_field.type_body_len != 0);30729 assert(zir_field.type_body_len != 0);
30713 const body = zir.extra[extra_index..][0..zir_field.type_body_len];30730 const body = zir.extra[extra_index..][0..zir_field.type_body_len];
30714 extra_index += body.len;30731 extra_index += body.len;
30715 const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);30732 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 };
30717 };30744 };
30718 if (field_ty.tag() == .generic_poison) {30745 if (field_ty.tag() == .generic_poison) {
30719 return error.GenericPoison;30746 return error.GenericPoison;
30720 }30747 }
3072130748
30722 const field = &struct_obj.fields.values()[i];30749 const field = &struct_obj.fields.values()[field_i];
30723 field.ty = try field_ty.copy(decl_arena_allocator);30750 field.ty = try field_ty.copy(decl_arena_allocator);
3072430751
30725 if (field_ty.zigTypeTag() == .Opaque) {30752 if (field_ty.zigTypeTag() == .Opaque) {
30726 const msg = msg: {30753 const msg = msg: {
30727 const tree = try sema.getAstTree(&block_scope);30754 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30728 const field_src = enumFieldSrcLoc(decl, tree.*, 0, i);30755 .index = field_i,
30729 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});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", .{});
30730 errdefer msg.destroy(sema.gpa);30759 errdefer msg.destroy(sema.gpa);
3073130760
30732 try sema.addDeclaredHereNote(msg, field_ty);30761 try sema.addDeclaredHereNote(msg, field_ty);
...@@ -30736,9 +30765,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30736,9 +30765,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30736 }30765 }
30737 if (field_ty.zigTypeTag() == .NoReturn) {30766 if (field_ty.zigTypeTag() == .NoReturn) {
30738 const msg = msg: {30767 const msg = msg: {
30739 const tree = try sema.getAstTree(&block_scope);30768 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30740 const field_src = enumFieldSrcLoc(decl, tree.*, 0, i);30769 .index = field_i,
30741 const msg = try sema.errMsg(&block_scope, field_src, "struct fields cannot be 'noreturn'", .{});30770 .range = .type,
30771 }).lazy;
30772 const msg = try sema.errMsg(&block_scope, ty_src, "struct fields cannot be 'noreturn'", .{});
30742 errdefer msg.destroy(sema.gpa);30773 errdefer msg.destroy(sema.gpa);
3074330774
30744 try sema.addDeclaredHereNote(msg, field_ty);30775 try sema.addDeclaredHereNote(msg, field_ty);
...@@ -30748,12 +30779,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30748,12 +30779,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30748 }30779 }
30749 if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) {30780 if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) {
30750 const msg = msg: {30781 const msg = msg: {
30751 const tree = try sema.getAstTree(&block_scope);30782 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30752 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);30783 .index = field_i,
30753 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});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)});
30754 errdefer msg.destroy(sema.gpa);30787 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
30758 try sema.addDeclaredHereNote(msg, field.ty);30791 try sema.addDeclaredHereNote(msg, field.ty);
30759 break :msg msg;30792 break :msg msg;
...@@ -30761,12 +30794,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30761,12 +30794,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30761 return sema.failWithOwnedErrorMsg(msg);30794 return sema.failWithOwnedErrorMsg(msg);
30762 } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {30795 } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
30763 const msg = msg: {30796 const msg = msg: {
30764 const tree = try sema.getAstTree(&block_scope);30797 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30765 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);30798 .index = field_i,
30766 const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});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)});
30767 errdefer msg.destroy(sema.gpa);30802 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
30771 try sema.addDeclaredHereNote(msg, field.ty);30806 try sema.addDeclaredHereNote(msg, field.ty);
30772 break :msg msg;30807 break :msg msg;
...@@ -30778,7 +30813,17 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30778,7 +30813,17 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30778 const body = zir.extra[extra_index..][0..zir_field.align_body_len];30813 const body = zir.extra[extra_index..][0..zir_field.align_body_len];
30779 extra_index += body.len;30814 extra_index += body.len;
30780 const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);30815 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 };
30782 }30827 }
3078330828
30784 extra_index += zir_field.init_body_len;30829 extra_index += zir_field.init_body_len;
...@@ -30788,26 +30833,30 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30788,26 +30833,30 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3078830833
30789 if (any_inits) {30834 if (any_inits) {
30790 extra_index = bodies_index;30835 extra_index = bodies_index;
30791 for (fields) |zir_field, i| {30836 for (fields) |zir_field, field_i| {
30792 extra_index += zir_field.type_body_len;30837 extra_index += zir_field.type_body_len;
30793 extra_index += zir_field.align_body_len;30838 extra_index += zir_field.align_body_len;
30794 if (zir_field.init_body_len > 0) {30839 if (zir_field.init_body_len > 0) {
30795 const body = zir.extra[extra_index..][0..zir_field.init_body_len];30840 const body = zir.extra[extra_index..][0..zir_field.init_body_len];
30796 extra_index += body.len;30841 extra_index += body.len;
30797 const init = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);30842 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];
30799 const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {30844 const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {
30800 error.NeededSourceLocation => {30845 error.NeededSourceLocation => {
30801 const tree = try sema.getAstTree(&block_scope);30846 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{
30802 const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);30847 .index = field_i,
30848 .range = .value,
30849 }).lazy;
30803 _ = try sema.coerce(&block_scope, field.ty, init, init_src);30850 _ = try sema.coerce(&block_scope, field.ty, init, init_src);
30804 unreachable;30851 unreachable;
30805 },30852 },
30806 else => |e| return e,30853 else => |e| return e,
30807 };30854 };
30808 const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {30855 const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
30809 const tree = try sema.getAstTree(&block_scope);30856 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{
30810 const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);30857 .index = field_i,
30858 .range = .value,
30859 }).lazy;
30811 return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known");30860 return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known");
30812 };30861 };
30813 field.default_val = try default_val.copy(decl_arena_allocator);30862 field.default_val = try default_val.copy(decl_arena_allocator);
...@@ -31023,9 +31072,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31023,9 +31072,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3102331072
31024 if (enum_value_map) |map| {31073 if (enum_value_map) |map| {
31025 const copied_val = if (tag_ref != .none) blk: {31074 const copied_val = if (tag_ref != .none) blk: {
31026 const tag_src = src; // TODO better source location31075 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {
31027 const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, tag_src);31076 error.NeededSourceLocation => {
31028 const val = try sema.resolveConstValue(&block_scope, tag_src, coerced, "enum tag value must be comptime-known");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 };
31029 last_tag_val = val;31086 last_tag_val = val;
3103031087
31031 // This puts the memory into the union arena, not the enum arena, but31088 // 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 {...@@ -31045,9 +31102,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31045 .mod = mod,31102 .mod = mod,
31046 });31103 });
31047 if (gop.found_existing) {31104 if (gop.found_existing) {
31048 const tree = try sema.getAstTree(&block_scope);31105 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
31049 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, field_i);31106 const other_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = gop.index }).lazy;
31050 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, gop.index);
31051 const msg = msg: {31107 const msg = msg: {
31052 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});31108 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});
31053 errdefer msg.destroy(gpa);31109 errdefer msg.destroy(gpa);
...@@ -31069,10 +31125,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31069,10 +31125,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31069 else if (field_type_ref == .none)31125 else if (field_type_ref == .none)
31070 Type.initTag(.noreturn)31126 Type.initTag(.noreturn)
31071 else31127 else
31072 // TODO: if we need to report an error here, use a source location31128 sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) {
31073 // that points to this type expression rather than the union.31129 error.NeededSourceLocation => {
31074 // But only resolve the source location if we need to emit a compile error.31130 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31075 try sema.resolveType(&block_scope, src, field_type_ref);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
31077 if (field_ty.tag() == .generic_poison) {31140 if (field_ty.tag() == .generic_poison) {
31078 return error.GenericPoison;31141 return error.GenericPoison;
...@@ -31081,13 +31144,12 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31081,13 +31144,12 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31081 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);31144 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
31082 if (gop.found_existing) {31145 if (gop.found_existing) {
31083 const msg = msg: {31146 const msg = msg: {
31084 const tree = try sema.getAstTree(&block_scope);31147 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
31085 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
31086 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name});31148 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name});
31087 errdefer msg.destroy(gpa);31149 errdefer msg.destroy(gpa);
3108831150
31089 const prev_field_index = union_obj.fields.getIndex(field_name).?;31151 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;
31091 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});31153 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});
31092 try sema.errNote(&block_scope, src, msg, "union declared here", .{});31154 try sema.errNote(&block_scope, src, msg, "union declared here", .{});
31093 break :msg msg;31155 break :msg msg;
...@@ -31099,9 +31161,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31099,9 +31161,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31099 const enum_has_field = names.orderedRemove(field_name);31161 const enum_has_field = names.orderedRemove(field_name);
31100 if (!enum_has_field) {31162 if (!enum_has_field) {
31101 const msg = msg: {31163 const msg = msg: {
31102 const tree = try sema.getAstTree(&block_scope);31164 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31103 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31165 .index = 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) });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) });
31105 errdefer msg.destroy(sema.gpa);31169 errdefer msg.destroy(sema.gpa);
31106 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);31170 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
31107 break :msg msg;31171 break :msg msg;
...@@ -31112,9 +31176,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31112,9 +31176,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3111231176
31113 if (field_ty.zigTypeTag() == .Opaque) {31177 if (field_ty.zigTypeTag() == .Opaque) {
31114 const msg = msg: {31178 const msg = msg: {
31115 const tree = try sema.getAstTree(&block_scope);31179 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31116 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31180 .index = 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", .{});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", .{});
31118 errdefer msg.destroy(sema.gpa);31184 errdefer msg.destroy(sema.gpa);
3111931185
31120 try sema.addDeclaredHereNote(msg, field_ty);31186 try sema.addDeclaredHereNote(msg, field_ty);
...@@ -31124,12 +31190,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31124,12 +31190,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31124 }31190 }
31125 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {31191 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {
31126 const msg = msg: {31192 const msg = msg: {
31127 const tree = try sema.getAstTree(&block_scope);31193 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31128 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31194 .index = field_i,
31129 const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});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)});
31130 errdefer msg.destroy(sema.gpa);31198 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
31134 try sema.addDeclaredHereNote(msg, field_ty);31202 try sema.addDeclaredHereNote(msg, field_ty);
31135 break :msg msg;31203 break :msg msg;
...@@ -31137,12 +31205,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31137,12 +31205,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31137 return sema.failWithOwnedErrorMsg(msg);31205 return sema.failWithOwnedErrorMsg(msg);
31138 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {31206 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
31139 const msg = msg: {31207 const msg = msg: {
31140 const tree = try sema.getAstTree(&block_scope);31208 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31141 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31209 .index = field_i,
31142 const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});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)});
31143 errdefer msg.destroy(sema.gpa);31213 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
31147 try sema.addDeclaredHereNote(msg, field_ty);31217 try sema.addDeclaredHereNote(msg, field_ty);
31148 break :msg msg;31218 break :msg msg;
...@@ -31156,10 +31226,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31156,10 +31226,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31156 };31226 };
3115731227
31158 if (align_ref != .none) {31228 if (align_ref != .none) {
31159 // TODO: if we need to report an error here, use a source location31229 gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
31160 // that points to this alignment expression rather than the struct.31230 error.NeededSourceLocation => {
31161 // But only resolve the source location if we need to emit a compile error.31231 const align_src = union_obj.fieldSrcLoc(sema.mod, .{
31162 gop.value_ptr.abi_align = try sema.resolveAlign(&block_scope, src, align_ref);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 };
31163 } else {31240 } else {
31164 gop.value_ptr.abi_align = 0;31241 gop.value_ptr.abi_align = 0;
31165 }31242 }
...@@ -31184,6 +31261,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31184,6 +31261,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31184 }31261 }
31185}31262}
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
31187fn generateUnionTagTypeNumbered(31269fn generateUnionTagTypeNumbered(
31188 sema: *Sema,31270 sema: *Sema,
31189 block: *Block,31271 block: *Block,
...@@ -31607,102 +31689,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -31607,102 +31689,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
31607 }31689 }
31608}31690}
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
31706/// Returns the type of the AIR instruction.31692/// Returns the type of the AIR instruction.
31707fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {31693fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {
31708 return sema.getTmpAir().typeOf(inst);31694 return sema.getTmpAir().typeOf(inst);
...@@ -31792,14 +31778,6 @@ fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {...@@ -31792,14 +31778,6 @@ fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {
31792 return sema.addConstant(ty, try Value.Tag.int_u64.create(sema.arena, int));31778 return sema.addConstant(ty, try Value.Tag.int_u64.create(sema.arena, int));
31793}31779}
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
31803fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {31781fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {
31804 return sema.addConstant(ty, Value.undef);31782 return sema.addConstant(ty, Value.undef);
31805}31783}
...@@ -32443,27 +32421,6 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {...@@ -32443,27 +32421,6 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {
32443 return Value.fromBigInt(sema.arena, result_bigint.toConst());32421 return Value.fromBigInt(sema.arena, result_bigint.toConst());
32444}32422}
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
32467/// Supports both floats and ints; handles undefined.32424/// Supports both floats and ints; handles undefined.
32468fn numberAddWrapScalar(32425fn numberAddWrapScalar(
32469 sema: *Sema,32426 sema: *Sema,
...@@ -32522,27 +32479,6 @@ fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {...@@ -32522,27 +32479,6 @@ fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {
32522 return Value.fromBigInt(sema.arena, result_bigint.toConst());32479 return Value.fromBigInt(sema.arena, result_bigint.toConst());
32523}32480}
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
32546/// Supports both floats and ints; handles undefined.32482/// Supports both floats and ints; handles undefined.
32547fn numberSubWrapScalar(32483fn numberSubWrapScalar(
32548 sema: *Sema,32484 sema: *Sema,
src/Zir.zig+1-2
...@@ -100,8 +100,7 @@ pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {...@@ -100,8 +100,7 @@ pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {
100100
101pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {101pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
102 const raw_slice = code.extra[start..][0..len];102 const raw_slice = code.extra[start..][0..len];
103 // TODO we should be able to directly `@ptrCast` the slice to the other slice type.103 return @ptrCast([]Inst.Ref, raw_slice);
104 return @ptrCast([*]Inst.Ref, raw_slice.ptr)[0..len];
105}104}
106105
107pub fn hasCompileErrors(code: Zir) bool {106pub fn hasCompileErrors(code: Zir) bool {
src/main.zig+1-2
...@@ -3454,8 +3454,7 @@ fn runOrTest(...@@ -3454,8 +3454,7 @@ fn runOrTest(
3454 } else if (watch) {3454 } else if (watch) {
3455 warn("process exited with code {d}", .{code});3455 warn("process exited with code {d}", .{code});
3456 } else {3456 } else {
3457 // TODO https://github.com/ziglang/zig/issues/63423457 process.exit(code);
3458 process.exit(1);
3459 }3458 }
3460 },3459 },
3461 else => {3460 else => {
src/type.zig+2-44
...@@ -1236,7 +1236,7 @@ pub const Type = extern union {...@@ -1236,7 +1236,7 @@ pub const Type = extern union {
1236 // we can't hash these based on tags because they wouldn't match the expanded version.1236 // we can't hash these based on tags because they wouldn't match the expanded version.
1237 .type_info => unreachable, // needed to resolve the type before now1237 .type_info => unreachable, // needed to resolve the type before now
12381238
1239 .bound_fn => unreachable, // TODO delete from the language1239 .bound_fn => unreachable,
1240 .var_args_param => unreachable, // can be any type1240 .var_args_param => unreachable, // can be any type
1241 }1241 }
1242 }1242 }
...@@ -3272,7 +3272,7 @@ pub const Type = extern union {...@@ -3272,7 +3272,7 @@ pub const Type = extern union {
3272 .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer3272 .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer
3273 .function => unreachable, // represents machine code; not a pointer3273 .function => unreachable, // represents machine code; not a pointer
3274 .@"opaque" => unreachable, // no size available3274 .@"opaque" => unreachable, // no size available
3275 .bound_fn => unreachable, // TODO remove from the language3275 .bound_fn => unreachable,
3276 .noreturn => unreachable,3276 .noreturn => unreachable,
3277 .inferred_alloc_const => unreachable,3277 .inferred_alloc_const => unreachable,
3278 .inferred_alloc_mut => unreachable,3278 .inferred_alloc_mut => unreachable,
...@@ -4088,47 +4088,6 @@ pub const Type = extern union {...@@ -4088,47 +4088,6 @@ pub const Type = extern union {
4088 }4088 }
4089 }4089 }
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
4132 /// For *[N]T, returns [N]T.4091 /// For *[N]T, returns [N]T.
4133 /// For *T, returns T.4092 /// For *T, returns T.
4134 /// For [*]T, returns T.4093 /// For [*]T, returns T.
...@@ -5434,7 +5393,6 @@ pub const Type = extern union {...@@ -5434,7 +5393,6 @@ pub const Type = extern union {
5434 }5393 }
54355394
5436 /// Asserts the type is an enum or a union.5395 /// Asserts the type is an enum or a union.
5437 /// TODO support unions
5438 pub fn intTagType(ty: Type, buffer: *Payload.Bits) Type {5396 pub fn intTagType(ty: Type, buffer: *Payload.Bits) Type {
5439 switch (ty.tag()) {5397 switch (ty.tag()) {
5440 .enum_full, .enum_nonexhaustive => return ty.cast(Payload.EnumFull).?.data.tag_ty,5398 .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 {...@@ -814,7 +814,6 @@ pub const Value = extern union {
814 .float_80 => return out_stream.print("{}", .{val.castTag(.float_80).?.data}),814 .float_80 => return out_stream.print("{}", .{val.castTag(.float_80).?.data}),
815 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),815 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
816 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),816 .@"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
818 .eu_payload => {817 .eu_payload => {
819 try out_stream.writeAll("(eu_payload) ");818 try out_stream.writeAll("(eu_payload) ");
820 val = val.castTag(.eu_payload).?.data;819 val = val.castTag(.eu_payload).?.data;
...@@ -989,8 +988,7 @@ pub const Value = extern union {...@@ -989,8 +988,7 @@ pub const Value = extern union {
989 switch (val.tag()) {988 switch (val.tag()) {
990 .enum_field_index => {989 .enum_field_index => {
991 const field_index = val.castTag(.enum_field_index).?.data;990 const field_index = val.castTag(.enum_field_index).?.data;
992 // TODO should `@intToEnum` do this `@intCast` for you?991 return @intToEnum(E, field_index);
993 return @intToEnum(E, @intCast(@typeInfo(E).Enum.tag_type, field_index));
994 },992 },
995 .the_only_possible_value => {993 .the_only_possible_value => {
996 const fields = std.meta.fields(E);994 const fields = std.meta.fields(E);
test/behavior/enum.zig+10
...@@ -1185,3 +1185,13 @@ test "runtime int to enum with one possible value" {...@@ -1185,3 +1185,13 @@ test "runtime int to enum with one possible value" {
1185 @compileError("test failed");1185 @compileError("test failed");
1186 }1186 }
1187}1187}
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 {...@@ -29,9 +29,9 @@ export fn d() void {
29// backend=stage229// backend=stage2
30// target=native30// target=native
31//31//
32// :3:5: error: opaque types have unknown size and therefore cannot be directly embedded in structs32// :3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs
33// :1:11: note: opaque declared here33// :1:11: note: opaque declared here
34// :7:5: error: opaque types have unknown size and therefore cannot be directly embedded in unions34// :7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions
35// :19:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs35// :19:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs
36// :18:22: note: opaque declared here36// :18:22: note: opaque declared here
37// :24:23: error: opaque types have unknown size and therefore cannot be directly embedded in structs37// :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 {...@@ -14,5 +14,5 @@ export fn entry() void {
14// backend=stage214// backend=stage2
15// target=native15// target=native
16//16//
17// :6:5: error: enum tag value 60 already taken17// :6:9: error: enum tag value 60 already taken
18// :4:5: note: other occurrence here18// :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 {...@@ -39,7 +39,7 @@ export fn entry() void {
39// backend=stage239// backend=stage2
40// target=native40// target=native
41//41//
42// :31:5: error: extern structs cannot contain fields of type 'tmp.E'42// :31:8: error: extern structs cannot contain fields of type 'tmp.E'
43// :31:5: note: enum tag type 'u9' is not extern compatible43// :31:8: note: enum tag type 'u9' is not extern compatible
44// :31:5: note: only integers with power of two bits are extern compatible44// :31:8: note: only integers with power of two bits are extern compatible
45// :1:15: note: enum declared here45// :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 {...@@ -11,7 +11,7 @@ export fn entry() void {
11// backend=stage211// backend=stage2
12// target=native12// target=native
13//13//
14// :3:5: error: extern structs cannot contain fields of type 'tmp.E'14// :3:8: error: extern structs cannot contain fields of type 'tmp.E'
15// :3:5: note: enum tag type 'u31' is not extern compatible15// :3:8: note: enum tag type 'u31' is not extern compatible
16// :3:5: note: only integers with power of two bits are extern compatible16// :3:8: note: only integers with power of two bits are extern compatible
17// :1:15: note: enum declared here17// :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; }...@@ -7,5 +7,5 @@ export fn testf(fluff: *stroo) void { _ = fluff; }
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:5: error: extern structs cannot contain fields of type '?[*c]u8'10// :2:10: error: extern structs cannot contain fields of type '?[*c]u8'
11// :2:5: note: only pointer like optionals are extern compatible11// :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 {...@@ -9,4 +9,4 @@ comptime {
9// backend=stage29// backend=stage2
10// target=native10// target=native
11//11//
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 {...@@ -12,9 +12,9 @@ comptime {
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
15// :2:5: error: extern structs cannot contain fields of type 'fn() callconv(.C) void'15// :2:8: error: extern structs cannot contain fields of type 'fn() callconv(.C) void'
16// :2:5: note: type has no guaranteed in-memory representation16// :2:8: note: type has no guaranteed in-memory representation
17// :2:5: note: use '*const ' to make a function pointer type17// :2:8: note: use '*const ' to make a function pointer type
18// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn() callconv(.C) void'18// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn() callconv(.C) void'
19// :8:13: note: type has no guaranteed in-memory representation19// :8:13: note: type has no guaranteed in-memory representation
20// :8:13: note: use '*const ' to make a function pointer type20// :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 {...@@ -70,22 +70,22 @@ export fn entry12() void {
70// backend=llvm70// backend=llvm
71// target=native71// target=native
72//72//
73// :3:9: error: packed structs cannot contain fields of type 'anyerror'73// :3:12: error: packed structs cannot contain fields of type 'anyerror'
74// :3:9: note: type has no guaranteed in-memory representation74// :3:12: note: type has no guaranteed in-memory representation
75// :8:9: error: packed structs cannot contain fields of type '[2]u24'75// :8:12: error: packed structs cannot contain fields of type '[2]u24'
76// :8:9: note: type has no guaranteed in-memory representation76// :8:12: note: type has no guaranteed in-memory representation
77// :13:9: error: packed structs cannot contain fields of type 'anyerror!u32'77// :13:20: error: packed structs cannot contain fields of type 'anyerror!u32'
78// :13:9: note: type has no guaranteed in-memory representation78// :13:20: note: type has no guaranteed in-memory representation
79// :18:9: error: packed structs cannot contain fields of type 'tmp.S'79// :18:12: error: packed structs cannot contain fields of type 'tmp.S'
80// :18:9: note: only packed structs layout are allowed in packed types80// :18:12: note: only packed structs layout are allowed in packed types
81// :56:11: note: struct declared here81// :56:11: note: struct declared here
82// :23:9: error: packed structs cannot contain fields of type 'tmp.U'82// :23:12: error: packed structs cannot contain fields of type 'tmp.U'
83// :23:9: note: only packed unions layout are allowed in packed types83// :23:12: note: only packed unions layout are allowed in packed types
84// :59:18: note: union declared here84// :59:18: note: union declared here
85// :28:9: error: packed structs cannot contain fields of type '?anyerror'85// :28:12: error: packed structs cannot contain fields of type '?anyerror'
86// :28:9: note: type has no guaranteed in-memory representation86// :28:12: note: type has no guaranteed in-memory representation
87// :38:9: error: packed structs cannot contain fields of type 'fn() void'87// :38:12: error: packed structs cannot contain fields of type 'fn() void'
88// :38:9: note: type has no guaranteed in-memory representation88// :38:12: note: type has no guaranteed in-memory representation
89// :38:9: note: use '*const ' to make a function pointer type89// :38:12: note: use '*const ' to make a function pointer type
90// :65:28: error: packed structs cannot contain fields of type '[]u8'90// :65:31: error: packed structs cannot contain fields of type '[]u8'
91// :65:28: note: slices have no guaranteed in-memory representation91// :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 {...@@ -15,6 +15,6 @@ export fn entry() void {
15// backend=stage215// backend=stage2
16// target=native16// target=native
17//17//
18// :6:5: error: packed unions cannot contain fields of type 'tmp.Foo'18// :6:8: error: packed unions cannot contain fields of type 'tmp.Foo'
19// :6:5: note: only packed structs layout are allowed in packed types19// :6:8: note: only packed structs layout are allowed in packed types
20// :1:13: note: struct declared here20// :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 {...@@ -18,5 +18,5 @@ export fn entry() void {
18// backend=stage218// backend=stage2
19// target=native19// target=native
20//20//
21// :10:5: error: no field named 'D' in enum 'tmp.Letter'21// :10:8: error: no field named 'D' in enum 'tmp.Letter'
22// :1:16: note: enum declared here22// :1:16: note: enum declared here
test/cases/compile_errors/union_extra_field.zig+1-1
...@@ -16,5 +16,5 @@ export fn entry() usize {...@@ -16,5 +16,5 @@ export fn entry() usize {
16// error16// error
17// target=native17// target=native
18//18//
19// :10:5: error: no field named 'd' in enum 'tmp.E'19// :10:8: error: no field named 'd' in enum 'tmp.E'
20// :1:11: note: enum declared here20// :1:11: note: enum declared here