authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 18:39:48-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 18:39:48-07:00
log0efc6a35bead74b5faffbc87b446b5087f1bb99b
tree6b8eaabe33a371d366c0be57b76c57e458d963e4
parent1d5f865cfafdaa96cac35ada9bb9e8b1a4e2bc36

Sema: fix enum value without tag name used as switch item

Previously stage2 would report a false positive compile error saying there was no tag for this value.

2 files changed, 27 insertions(+), 19 deletions(-)

src/Sema.zig+9-19
......@@ -8378,9 +8378,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
83788378 .Enum => {
83798379 var seen_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount());
83808380 defer gpa.free(seen_fields);
8381
83828381 mem.set(?Module.SwitchProngSrc, seen_fields, null);
83838382
8383 // This is used for non-exhaustive enum values that do not correspond to any tags.
8384 var range_set = RangeSet.init(gpa, sema.mod);
8385 defer range_set.deinit();
8386
83848387 var extra_index: usize = special.end;
83858388 {
83868389 var scalar_i: u32 = 0;
......@@ -8394,6 +8397,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
83948397 try sema.validateSwitchItemEnum(
83958398 block,
83968399 seen_fields,
8400 &range_set,
83978401 item_ref,
83988402 src_node_offset,
83998403 .{ .scalar = scalar_i },
......@@ -8416,6 +8420,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
84168420 try sema.validateSwitchItemEnum(
84178421 block,
84188422 seen_fields,
8423 &range_set,
84198424 item_ref,
84208425 src_node_offset,
84218426 .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
......@@ -9317,30 +9322,15 @@ fn validateSwitchItemEnum(
93179322 sema: *Sema,
93189323 block: *Block,
93199324 seen_fields: []?Module.SwitchProngSrc,
9325 range_set: *RangeSet,
93209326 item_ref: Zir.Inst.Ref,
93219327 src_node_offset: i32,
93229328 switch_prong_src: Module.SwitchProngSrc,
93239329) CompileError!void {
93249330 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
93259331 const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse {
9326 const msg = msg: {
9327 const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .none);
9328 const msg = try sema.errMsg(
9329 block,
9330 src,
9331 "enum '{}' has no tag with value '{}'",
9332 .{ item_tv.ty.fmt(sema.mod), item_tv.val.fmtValue(item_tv.ty, sema.mod) },
9333 );
9334 errdefer msg.destroy(sema.gpa);
9335 try sema.mod.errNoteNonLazy(
9336 item_tv.ty.declSrcLoc(sema.mod),
9337 msg,
9338 "enum declared here",
9339 .{},
9340 );
9341 break :msg msg;
9342 };
9343 return sema.failWithOwnedErrorMsg(block, msg);
9332 const maybe_prev_src = try range_set.add(item_tv.val, item_tv.val, item_tv.ty, switch_prong_src);
9333 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
93449334 };
93459335 const maybe_prev_src = seen_fields[field_index];
93469336 seen_fields[field_index] = switch_prong_src;
test/behavior/switch.zig+18
......@@ -672,3 +672,21 @@ test "capture of integer forwards the switch condition directly" {
672672 comptime try S.foo(42);
673673 comptime try S.foo(100);
674674}
675
676test "enum value without tag name used as switch item" {
677 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
678 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
679
680 const E = enum(u32) {
681 a = 1,
682 b = 2,
683 _,
684 };
685 var e: E = @intToEnum(E, 0);
686 switch (e) {
687 @intToEnum(E, 0) => {},
688 .a => return error.TestFailed,
689 .b => return error.TestFailed,
690 _ => return error.TestFailed,
691 }
692}