Commit 0efc6a35be
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -8378,9 +8378,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
.Enum => {
var seen_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount());
defer gpa.free(seen_fields);
-
mem.set(?Module.SwitchProngSrc, seen_fields, null);
+ // This is used for non-exhaustive enum values that do not correspond to any tags.
+ var range_set = RangeSet.init(gpa, sema.mod);
+ defer range_set.deinit();
+
var extra_index: usize = special.end;
{
var scalar_i: u32 = 0;
@@ -8394,6 +8397,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
try sema.validateSwitchItemEnum(
block,
seen_fields,
+ &range_set,
item_ref,
src_node_offset,
.{ .scalar = scalar_i },
@@ -8416,6 +8420,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
try sema.validateSwitchItemEnum(
block,
seen_fields,
+ &range_set,
item_ref,
src_node_offset,
.{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
@@ -9317,30 +9322,15 @@ fn validateSwitchItemEnum(
sema: *Sema,
block: *Block,
seen_fields: []?Module.SwitchProngSrc,
+ range_set: *RangeSet,
item_ref: Zir.Inst.Ref,
src_node_offset: i32,
switch_prong_src: Module.SwitchProngSrc,
) CompileError!void {
const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse {
- const msg = msg: {
- const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .none);
- const msg = try sema.errMsg(
- block,
- src,
- "enum '{}' has no tag with value '{}'",
- .{ item_tv.ty.fmt(sema.mod), item_tv.val.fmtValue(item_tv.ty, sema.mod) },
- );
- errdefer msg.destroy(sema.gpa);
- try sema.mod.errNoteNonLazy(
- item_tv.ty.declSrcLoc(sema.mod),
- msg,
- "enum declared here",
- .{},
- );
- break :msg msg;
- };
- return sema.failWithOwnedErrorMsg(block, msg);
+ const maybe_prev_src = try range_set.add(item_tv.val, item_tv.val, item_tv.ty, switch_prong_src);
+ return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
};
const maybe_prev_src = seen_fields[field_index];
seen_fields[field_index] = switch_prong_src;
test/behavior/switch.zig
@@ -672,3 +672,21 @@ test "capture of integer forwards the switch condition directly" {
comptime try S.foo(42);
comptime try S.foo(100);
}
+
+test "enum value without tag name used as switch item" {
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+ const E = enum(u32) {
+ a = 1,
+ b = 2,
+ _,
+ };
+ var e: E = @intToEnum(E, 0);
+ switch (e) {
+ @intToEnum(E, 0) => {},
+ .a => return error.TestFailed,
+ .b => return error.TestFailed,
+ _ => return error.TestFailed,
+ }
+}