Skip to content

Commit 0efc6a3

Browse files
committed
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.
1 parent 1d5f865 commit 0efc6a3

File tree

2 files changed

+27
-19
lines changed

2 files changed

+27
-19
lines changed

src/Sema.zig

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
676+
test "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+
}

0 commit comments

Comments
 (0)