authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-05 21:37:30+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-05 22:03:32+02:00
logf2faa303a541f5adddbba26d04dc2749991e0075
tree5761621aa62e2a36551a33138c4f90a38f3795c0
parent8c4727f9ab61e4c99ab2a00f5751f9b11d274fbe

Sema: handle enum expressions referencing local variables

Closes #12272

5 files changed, 180 insertions(+), 225 deletions(-)

src/AstGen.zig+23-13
......@@ -2013,7 +2013,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
20132013 },
20142014 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
20152015 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2016 .namespace => break,
2016 .namespace, .enum_namespace => break,
20172017 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
20182018 .top => unreachable,
20192019 }
......@@ -2088,7 +2088,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
20882088 try parent_gz.addDefer(defer_scope.index, defer_scope.len);
20892089 },
20902090 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2091 .namespace => break,
2091 .namespace, .enum_namespace => break,
20922092 .top => unreachable,
20932093 }
20942094 }
......@@ -2179,7 +2179,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke
21792179 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
21802180 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
21812181 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2182 .namespace => break,
2182 .namespace, .enum_namespace => break,
21832183 .top => unreachable,
21842184 }
21852185 }
......@@ -2729,7 +2729,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct {
27292729 const have_err_payload = defer_scope.remapped_err_code != 0;
27302730 need_err_code = need_err_code or have_err_payload;
27312731 },
2732 .namespace => unreachable,
2732 .namespace, .enum_namespace => unreachable,
27332733 .top => unreachable,
27342734 }
27352735 }
......@@ -2799,7 +2799,7 @@ fn genDefers(
27992799 .normal_only => continue,
28002800 }
28012801 },
2802 .namespace => unreachable,
2802 .namespace, .enum_namespace => unreachable,
28032803 .top => unreachable,
28042804 }
28052805 }
......@@ -2835,7 +2835,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v
28352835 scope = s.parent;
28362836 },
28372837 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2838 .namespace => unreachable,
2838 .namespace, .enum_namespace => unreachable,
28392839 .top => unreachable,
28402840 }
28412841 }
......@@ -4278,7 +4278,7 @@ fn testDecl(
42784278 .local_val, .local_ptr => unreachable, // a test cannot be in a local scope
42794279 .gen_zir => s = s.cast(GenZir).?.parent,
42804280 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
4281 .namespace => {
4281 .namespace, .enum_namespace => {
42824282 const ns = s.cast(Scope.Namespace).?;
42834283 if (ns.decls.get(name_str_index)) |i| {
42844284 if (found_already) |f| {
......@@ -4963,6 +4963,7 @@ fn containerDecl(
49634963 defer block_scope.unstack();
49644964
49654965 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);
4966 namespace.base.tag = .enum_namespace;
49664967
49674968 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
49684969 try comptimeExpr(&block_scope, &namespace.base, .{ .rl = .{ .ty = .type_type } }, container_decl.ast.arg)
......@@ -4977,6 +4978,7 @@ fn containerDecl(
49774978 for (container_decl.ast.members) |member_node| {
49784979 if (member_node == counts.nonexhaustive_node)
49794980 continue;
4981 namespace.base.tag = .namespace;
49804982 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
49814983 .decl => continue,
49824984 .field => |field| field,
......@@ -5010,6 +5012,7 @@ fn containerDecl(
50105012 },
50115013 );
50125014 }
5015 namespace.base.tag = .enum_namespace;
50135016 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);
50145017 wip_members.appendToField(@enumToInt(tag_value_inst));
50155018 }
......@@ -7296,7 +7299,7 @@ fn localVarRef(
72967299 },
72977300 .gen_zir => s = s.cast(GenZir).?.parent,
72987301 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
7299 .namespace => {
7302 .namespace, .enum_namespace => {
73007303 const ns = s.cast(Scope.Namespace).?;
73017304 if (ns.decls.get(name_str_index)) |i| {
73027305 if (found_already) |f| {
......@@ -7308,7 +7311,7 @@ fn localVarRef(
73087311 // We found a match but must continue looking for ambiguous references to decls.
73097312 found_already = i;
73107313 }
7311 num_namespaces_out += 1;
7314 if (s.tag == .namespace) num_namespaces_out += 1;
73127315 capturing_namespace = ns;
73137316 s = ns.parent;
73147317 },
......@@ -7935,7 +7938,7 @@ fn builtinCall(
79357938 },
79367939 .gen_zir => s = s.cast(GenZir).?.parent,
79377940 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
7938 .namespace => {
7941 .namespace, .enum_namespace => {
79397942 const ns = s.cast(Scope.Namespace).?;
79407943 if (ns.decls.get(decl_name)) |i| {
79417944 if (found_already) |f| {
......@@ -10547,6 +10550,12 @@ const Scope = struct {
1054710550 else => return null,
1054810551 }
1054910552 }
10553 if (T == Namespace) {
10554 switch (base.tag) {
10555 .namespace, .enum_namespace => return @fieldParentPtr(T, "base", base),
10556 else => return null,
10557 }
10558 }
1055010559 if (base.tag != T.base_tag)
1055110560 return null;
1055210561
......@@ -10559,7 +10568,7 @@ const Scope = struct {
1055910568 .local_val => base.cast(LocalVal).?.parent,
1056010569 .local_ptr => base.cast(LocalPtr).?.parent,
1056110570 .defer_normal, .defer_error => base.cast(Defer).?.parent,
10562 .namespace => base.cast(Namespace).?.parent,
10571 .namespace, .enum_namespace => base.cast(Namespace).?.parent,
1056310572 .top => null,
1056410573 };
1056510574 }
......@@ -10571,6 +10580,7 @@ const Scope = struct {
1057110580 defer_normal,
1057210581 defer_error,
1057310582 namespace,
10583 enum_namespace,
1057410584 top,
1057510585 };
1057610586
......@@ -12247,7 +12257,7 @@ fn detectLocalShadowing(
1224712257 }
1224812258 s = local_ptr.parent;
1224912259 },
12250 .namespace => {
12260 .namespace, .enum_namespace => {
1225112261 outer_scope = true;
1225212262 const ns = s.cast(Scope.Namespace).?;
1225312263 const decl_node = ns.decls.get(ident_name) orelse {
......@@ -12415,7 +12425,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
1241512425 }
1241612426 s = local_ptr.parent;
1241712427 },
12418 .namespace => s = s.cast(Scope.Namespace).?.parent,
12428 .namespace, .enum_namespace => s = s.cast(Scope.Namespace).?.parent,
1241912429 .gen_zir => s = s.cast(GenZir).?.parent,
1242012430 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
1242112431 .top => break,
src/Module.zig+44-1
......@@ -1194,6 +1194,49 @@ pub const EnumFull = struct {
11941194 .lazy = LazySrcLoc.nodeOffset(0),
11951195 };
11961196 }
1197
1198 pub fn fieldSrcLoc(e: EnumFull, mod: *Module, query: FieldSrcQuery) SrcLoc {
1199 @setCold(true);
1200 const owner_decl = mod.declPtr(e.owner_decl);
1201 const file = owner_decl.getFileScope();
1202 const tree = file.getTree(mod.gpa) catch |err| {
1203 // In this case we emit a warning + a less precise source location.
1204 log.warn("unable to load {s}: {s}", .{
1205 file.sub_file_path, @errorName(err),
1206 });
1207 return e.srcLoc(mod);
1208 };
1209 const node = owner_decl.relativeToNodeIndex(0);
1210 const node_tags = tree.nodes.items(.tag);
1211 switch (node_tags[node]) {
1212 .container_decl,
1213 .container_decl_trailing,
1214 => return queryFieldSrc(tree.*, query, file, tree.containerDecl(node)),
1215 .container_decl_two, .container_decl_two_trailing => {
1216 var buffer: [2]Ast.Node.Index = undefined;
1217 return queryFieldSrc(tree.*, query, file, tree.containerDeclTwo(&buffer, node));
1218 },
1219 .container_decl_arg,
1220 .container_decl_arg_trailing,
1221 => return queryFieldSrc(tree.*, query, file, tree.containerDeclArg(node)),
1222
1223 .tagged_union,
1224 .tagged_union_trailing,
1225 => return queryFieldSrc(tree.*, query, file, tree.taggedUnion(node)),
1226 .tagged_union_two, .tagged_union_two_trailing => {
1227 var buffer: [2]Ast.Node.Index = undefined;
1228 return queryFieldSrc(tree.*, query, file, tree.taggedUnionTwo(&buffer, node));
1229 },
1230 .tagged_union_enum_tag,
1231 .tagged_union_enum_tag_trailing,
1232 => return queryFieldSrc(tree.*, query, file, tree.taggedUnionEnumTag(node)),
1233
1234 .root => return queryFieldSrc(tree.*, query, file, tree.containerDeclRoot()),
1235
1236 // This struct was generated using @Type
1237 else => return e.srcLoc(mod),
1238 }
1239 }
11971240};
11981241
11991242pub const Union = struct {
......@@ -6171,7 +6214,7 @@ pub const PeerTypeCandidateSrc = union(enum) {
61716214
61726215const FieldSrcQuery = struct {
61736216 index: usize,
6174 range: enum { name, type, value, alignment },
6217 range: enum { name, type, value, alignment } = .name,
61756218};
61766219
61776220fn queryFieldSrc(
src/Sema.zig+102-210
......@@ -2094,16 +2094,12 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS
20942094 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});
20952095 errdefer msg.destroy(sema.gpa);
20962096
2097 const decl_index = container_ty.getOwnerDeclOrNull() orelse break :msg msg;
2098 const decl = sema.mod.declPtr(decl_index);
2099 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {
2100 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
2101 return error.AnalysisFail;
2102 };
2103 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_index);
2104 const default_value_src: LazySrcLoc = .{ .node_offset_field_default = field_src.node_offset.x };
2105
2106 try sema.mod.errNoteNonLazy(default_value_src.toSrcLoc(decl), msg, "default value set here", .{});
2097 const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg;
2098 const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{
2099 .index = field_index,
2100 .range = .value,
2101 });
2102 try sema.mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{});
21072103 break :msg msg;
21082104 };
21092105 return sema.failWithOwnedErrorMsg(msg);
......@@ -2141,15 +2137,61 @@ fn addFieldErrNote(
21412137 comptime format: []const u8,
21422138 args: anytype,
21432139) !void {
2140 @setCold(true);
21442141 const mod = sema.mod;
21452142 const decl_index = container_ty.getOwnerDecl();
21462143 const decl = mod.declPtr(decl_index);
2147 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {
2148 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
2149 return error.AnalysisFail;
2144
2145 const field_src = blk: {
2146 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {
2147 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
2148 break :blk decl.srcLoc();
2149 };
2150
2151 const container_node = decl.relativeToNodeIndex(0);
2152 const node_tags = tree.nodes.items(.tag);
2153 var buffer: [2]std.zig.Ast.Node.Index = undefined;
2154 const container_decl = switch (node_tags[container_node]) {
2155 .root => tree.containerDeclRoot(),
2156 .container_decl,
2157 .container_decl_trailing,
2158 => tree.containerDecl(container_node),
2159 .container_decl_two,
2160 .container_decl_two_trailing,
2161 => tree.containerDeclTwo(&buffer, container_node),
2162 .container_decl_arg,
2163 .container_decl_arg_trailing,
2164 => tree.containerDeclArg(container_node),
2165 .tagged_union,
2166 .tagged_union_trailing,
2167 => tree.taggedUnion(container_node),
2168 .tagged_union_two,
2169 .tagged_union_two_trailing,
2170 => tree.taggedUnionTwo(&buffer, container_node),
2171 .tagged_union_enum_tag,
2172 .tagged_union_enum_tag_trailing,
2173 => tree.taggedUnionEnumTag(container_node),
2174 else => break :blk decl.srcLoc(),
2175 };
2176
2177 var it_index: usize = 0;
2178 for (container_decl.ast.members) |member_node| {
2179 switch (node_tags[member_node]) {
2180 .container_field_init,
2181 .container_field_align,
2182 .container_field,
2183 => {
2184 if (it_index == field_index) {
2185 break :blk decl.nodeOffsetSrcLoc(decl.nodeIndexToRelative(member_node));
2186 }
2187 it_index += 1;
2188 },
2189 else => continue,
2190 }
2191 }
2192 unreachable;
21502193 };
2151 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_index);
2152 try mod.errNoteNonLazy(field_src.toSrcLoc(decl), parent, format, args);
2194 try mod.errNoteNonLazy(field_src, parent, format, args);
21532195}
21542196
21552197fn errMsg(
......@@ -2863,7 +2905,7 @@ fn zirEnumDecl(
28632905 .inlining = null,
28642906 .is_comptime = true,
28652907 };
2866 defer assert(enum_block.instructions.items.len == 0); // should all be comptime instructions
2908 defer enum_block.instructions.deinit(sema.gpa);
28672909
28682910 if (body.len != 0) {
28692911 try sema.analyzeBody(&enum_block, body);
......@@ -2929,13 +2971,12 @@ fn zirEnumDecl(
29292971
29302972 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);
29312973 if (gop_field.found_existing) {
2932 const tree = try sema.getAstTree(block);
2933 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
2934 const other_tag_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_field.index);
2974 const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
2975 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_field.index }).lazy;
29352976 const msg = msg: {
29362977 const msg = try sema.errMsg(block, field_src, "duplicate enum field '{s}'", .{field_name});
29372978 errdefer msg.destroy(gpa);
2938 try sema.errNote(block, other_tag_src, msg, "other field here", .{});
2979 try sema.errNote(block, other_field_src, msg, "other field here", .{});
29392980 break :msg msg;
29402981 };
29412982 return sema.failWithOwnedErrorMsg(msg);
......@@ -2944,10 +2985,18 @@ fn zirEnumDecl(
29442985 if (has_tag_value) {
29452986 const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
29462987 extra_index += 1;
2947 // TODO: if we need to report an error here, use a source location
2948 // that points to this default value expression rather than the struct.
2949 // But only resolve the source location if we need to emit a compile error.
2950 const tag_val = (try sema.resolveInstConst(block, src, tag_val_ref, "enum tag value must be comptime-known")).val;
2988 const tag_inst = try sema.resolveInst(tag_val_ref);
2989 const tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) {
2990 error.NeededSourceLocation => {
2991 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
2992 .index = field_i,
2993 .range = .value,
2994 }).lazy;
2995 _ = try sema.resolveConstValue(block, value_src, tag_inst, "enum tag value must be comptime-known");
2996 unreachable;
2997 },
2998 else => |e| return e,
2999 };
29513000 last_tag_val = tag_val;
29523001 const copied_tag_val = try tag_val.copy(decl_arena_allocator);
29533002 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
......@@ -2955,11 +3004,13 @@ fn zirEnumDecl(
29553004 .mod = mod,
29563005 });
29573006 if (gop_val.found_existing) {
2958 const tree = try sema.getAstTree(block);
2959 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
2960 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_val.index);
3007 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3008 .index = field_i,
3009 .range = .value,
3010 }).lazy;
3011 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy;
29613012 const msg = msg: {
2962 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)});
29633014 errdefer msg.destroy(gpa);
29643015 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
29653016 break :msg msg;
......@@ -2978,9 +3029,8 @@ fn zirEnumDecl(
29783029 .mod = mod,
29793030 });
29803031 if (gop_val.found_existing) {
2981 const tree = try sema.getAstTree(block);
2982 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
2983 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_val.index);
3032 const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
3033 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy;
29843034 const msg = msg: {
29853035 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)});
29863036 errdefer msg.destroy(gpa);
......@@ -2998,9 +3048,11 @@ fn zirEnumDecl(
29983048 }
29993049
30003050 if (!(try sema.intFitsInType(last_tag_val.?, enum_obj.tag_ty, null))) {
3001 const tree = try sema.getAstTree(block);
3002 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
3003 const msg = try sema.errMsg(block, field_src, "enumeration value '{}' too large for type '{}'", .{
3051 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3052 .index = field_i,
3053 .range = if (has_tag_value) .value else .name,
3054 }).lazy;
3055 const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{
30043056 last_tag_val.?.fmtValue(enum_obj.tag_ty, mod), enum_obj.tag_ty.fmt(mod),
30053057 });
30063058 return sema.failWithOwnedErrorMsg(msg);
......@@ -30623,18 +30675,12 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3062330675 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
3062430676 if (gop.found_existing) {
3062530677 const msg = msg: {
30626 const field_src = struct_obj.fieldSrcLoc(sema.mod, .{
30627 .index = field_i,
30628 .range = .name,
30629 }).lazy;
30678 const field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
3063030679 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name});
3063130680 errdefer msg.destroy(gpa);
3063230681
3063330682 const prev_field_index = struct_obj.fields.getIndex(field_name).?;
30634 const prev_field_src = struct_obj.fieldSrcLoc(sema.mod, .{
30635 .index = prev_field_index,
30636 .range = .name,
30637 });
30683 const prev_field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index });
3063830684 try sema.mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
3063930685 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});
3064030686 break :msg msg;
......@@ -30787,26 +30833,30 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3078730833
3078830834 if (any_inits) {
3078930835 extra_index = bodies_index;
30790 for (fields) |zir_field, i| {
30836 for (fields) |zir_field, field_i| {
3079130837 extra_index += zir_field.type_body_len;
3079230838 extra_index += zir_field.align_body_len;
3079330839 if (zir_field.init_body_len > 0) {
3079430840 const body = zir.extra[extra_index..][0..zir_field.init_body_len];
3079530841 extra_index += body.len;
3079630842 const init = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
30797 const field = &struct_obj.fields.values()[i];
30843 const field = &struct_obj.fields.values()[field_i];
3079830844 const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {
3079930845 error.NeededSourceLocation => {
30800 const tree = try sema.getAstTree(&block_scope);
30801 const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);
30846 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{
30847 .index = field_i,
30848 .range = .value,
30849 }).lazy;
3080230850 _ = try sema.coerce(&block_scope, field.ty, init, init_src);
3080330851 unreachable;
3080430852 },
3080530853 else => |e| return e,
3080630854 };
3080730855 const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
30808 const tree = try sema.getAstTree(&block_scope);
30809 const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);
30856 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{
30857 .index = field_i,
30858 .range = .value,
30859 }).lazy;
3081030860 return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known");
3081130861 };
3081230862 field.default_val = try default_val.copy(decl_arena_allocator);
......@@ -31052,14 +31102,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3105231102 .mod = mod,
3105331103 });
3105431104 if (gop.found_existing) {
31055 const field_src = union_obj.fieldSrcLoc(sema.mod, .{
31056 .index = field_i,
31057 .range = .name,
31058 }).lazy;
31059 const other_field_src = union_obj.fieldSrcLoc(sema.mod, .{
31060 .index = gop.index,
31061 .range = .name,
31062 }).lazy;
31105 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
31106 const other_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = gop.index }).lazy;
3106331107 const msg = msg: {
3106431108 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});
3106531109 errdefer msg.destroy(gpa);
......@@ -31100,18 +31144,12 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3110031144 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
3110131145 if (gop.found_existing) {
3110231146 const msg = msg: {
31103 const field_src = union_obj.fieldSrcLoc(sema.mod, .{
31104 .index = field_i,
31105 .range = .name,
31106 }).lazy;
31147 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
3110731148 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name});
3110831149 errdefer msg.destroy(gpa);
3110931150
3111031151 const prev_field_index = union_obj.fields.getIndex(field_name).?;
31111 const prev_field_src = union_obj.fieldSrcLoc(sema.mod, .{
31112 .index = prev_field_index,
31113 .range = .name,
31114 }).lazy;
31152 const prev_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index }).lazy;
3111531153 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});
3111631154 try sema.errNote(&block_scope, src, msg, "union declared here", .{});
3111731155 break :msg msg;
......@@ -31651,102 +31689,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3165131689 }
3165231690}
3165331691
31654fn getAstTree(sema: *Sema, block: *Block) CompileError!*const std.zig.Ast {
31655 return block.namespace.file_scope.getTree(sema.gpa) catch |err| {
31656 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
31657 return error.AnalysisFail;
31658 };
31659}
31660
31661fn enumFieldSrcLoc(
31662 decl: *Decl,
31663 tree: std.zig.Ast,
31664 node_offset: i32,
31665 field_index: usize,
31666) LazySrcLoc {
31667 @setCold(true);
31668 const field_node = containerFieldNode(decl, tree, node_offset, field_index) orelse
31669 return LazySrcLoc.nodeOffset(0);
31670 return decl.nodeSrcLoc(field_node);
31671}
31672
31673fn containerFieldInitSrcLoc(
31674 decl: *Decl,
31675 tree: std.zig.Ast,
31676 node_offset: i32,
31677 field_index: usize,
31678) LazySrcLoc {
31679 @setCold(true);
31680 const node_tags = tree.nodes.items(.tag);
31681 const field_node = containerFieldNode(decl, tree, node_offset, field_index) orelse
31682 return LazySrcLoc.nodeOffset(0);
31683 const node_data = tree.nodes.items(.data)[field_node];
31684
31685 const init_node = switch (node_tags[field_node]) {
31686 .container_field_init => node_data.rhs,
31687 .container_field => blk: {
31688 const extra_data = tree.extraData(node_data.rhs, std.zig.Ast.Node.ContainerField);
31689 break :blk extra_data.value_expr;
31690 },
31691 else => unreachable,
31692 };
31693
31694 return decl.nodeSrcLoc(init_node);
31695}
31696
31697fn containerFieldNode(
31698 decl: *Decl,
31699 tree: std.zig.Ast,
31700 node_offset: i32,
31701 field_index: usize,
31702) ?std.zig.Ast.Node.Index {
31703 @setCold(true);
31704 const enum_node = decl.relativeToNodeIndex(node_offset);
31705 const node_tags = tree.nodes.items(.tag);
31706 var buffer: [2]std.zig.Ast.Node.Index = undefined;
31707 const container_decl = switch (node_tags[enum_node]) {
31708 .root => tree.containerDeclRoot(),
31709
31710 .container_decl,
31711 .container_decl_trailing,
31712 => tree.containerDecl(enum_node),
31713
31714 .container_decl_two,
31715 .container_decl_two_trailing,
31716 => tree.containerDeclTwo(&buffer, enum_node),
31717
31718 .container_decl_arg,
31719 .container_decl_arg_trailing,
31720 => tree.containerDeclArg(enum_node),
31721
31722 .tagged_union,
31723 .tagged_union_trailing,
31724 => tree.taggedUnion(enum_node),
31725 .tagged_union_two,
31726 .tagged_union_two_trailing,
31727 => tree.taggedUnionTwo(&buffer, enum_node),
31728 .tagged_union_enum_tag,
31729 .tagged_union_enum_tag_trailing,
31730 => tree.taggedUnionEnumTag(enum_node),
31731
31732 else => return null,
31733 };
31734 var it_index: usize = 0;
31735 for (container_decl.ast.members) |member_node| {
31736 switch (node_tags[member_node]) {
31737 .container_field_init,
31738 .container_field_align,
31739 .container_field,
31740 => {
31741 if (it_index == field_index) return member_node;
31742 it_index += 1;
31743 },
31744
31745 else => continue,
31746 }
31747 } else unreachable;
31748}
31749
3175031692/// Returns the type of the AIR instruction.
3175131693fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {
3175231694 return sema.getTmpAir().typeOf(inst);
......@@ -31836,14 +31778,6 @@ fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {
3183631778 return sema.addConstant(ty, try Value.Tag.int_u64.create(sema.arena, int));
3183731779}
3183831780
31839fn addBool(sema: *Sema, ty: Type, boolean: bool) CompileError!Air.Inst.Ref {
31840 return switch (ty.zigTypeTag()) {
31841 .Vector => sema.addConstant(ty, try Value.Tag.repeated.create(sema.arena, Value.makeBool(boolean))),
31842 .Bool => try sema.resolveInst(if (boolean) .bool_true else .bool_false),
31843 else => unreachable,
31844 };
31845}
31846
3184731781fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {
3184831782 return sema.addConstant(ty, Value.undef);
3184931783}
......@@ -32487,27 +32421,6 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {
3248732421 return Value.fromBigInt(sema.arena, result_bigint.toConst());
3248832422}
3248932423
32490/// Supports both (vectors of) floats and ints; handles undefined scalars.
32491fn numberAddWrap(
32492 sema: *Sema,
32493 lhs: Value,
32494 rhs: Value,
32495 ty: Type,
32496) !Value {
32497 if (ty.zigTypeTag() == .Vector) {
32498 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
32499 for (result_data) |*scalar, i| {
32500 var lhs_buf: Value.ElemValueBuffer = undefined;
32501 var rhs_buf: Value.ElemValueBuffer = undefined;
32502 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
32503 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
32504 scalar.* = try sema.numberAddWrapScalar(lhs_elem, rhs_elem, ty.scalarType());
32505 }
32506 return Value.Tag.aggregate.create(sema.arena, result_data);
32507 }
32508 return sema.numberAddWrapScalar(lhs, rhs, ty);
32509}
32510
3251132424/// Supports both floats and ints; handles undefined.
3251232425fn numberAddWrapScalar(
3251332426 sema: *Sema,
......@@ -32566,27 +32479,6 @@ fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {
3256632479 return Value.fromBigInt(sema.arena, result_bigint.toConst());
3256732480}
3256832481
32569/// Supports both (vectors of) floats and ints; handles undefined scalars.
32570fn numberSubWrap(
32571 sema: *Sema,
32572 lhs: Value,
32573 rhs: Value,
32574 ty: Type,
32575) !Value {
32576 if (ty.zigTypeTag() == .Vector) {
32577 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
32578 for (result_data) |*scalar, i| {
32579 var lhs_buf: Value.ElemValueBuffer = undefined;
32580 var rhs_buf: Value.ElemValueBuffer = undefined;
32581 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
32582 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
32583 scalar.* = try sema.numberSubWrapScalar(lhs_elem, rhs_elem, ty.scalarType());
32584 }
32585 return Value.Tag.aggregate.create(sema.arena, result_data);
32586 }
32587 return sema.numberSubWrapScalar(lhs, rhs, ty);
32588}
32589
3259032482/// Supports both floats and ints; handles undefined.
3259132483fn numberSubWrapScalar(
3259232484 sema: *Sema,
test/behavior/enum.zig+10
......@@ -1185,3 +1185,13 @@ test "runtime int to enum with one possible value" {
11851185 @compileError("test failed");
11861186 }
11871187}
1188
1189test "enum tag from a local variable" {
1190 const S = struct {
1191 fn Int(comptime Inner: type) type {
1192 return enum(Inner) { _ };
1193 }
1194 };
1195 const i = @intToEnum(S.Int(u32), 0);
1196 try std.testing.expect(@enumToInt(i) == 0);
1197}
test/cases/compile_errors/enum_value_already_taken.zig+1-1
......@@ -14,5 +14,5 @@ export fn entry() void {
1414// backend=stage2
1515// target=native
1616//
17// :6:5: error: enum tag value 60 already taken
17// :6:9: error: enum tag value 60 already taken
1818// :4:5: note: other occurrence here