From 57aa289fdef543a507d8da039f5b7e7f2762c878 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 7 Apr 2021 22:19:17 -0700 Subject: [PATCH] Sema: fix switch validation '_' prong on wrong type --- src/Sema.zig | 4 ++-- src/type.zig | 4 ++-- test/stage2/cbe.zig | 46 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index a0be08ed71..519d5df401 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1972,7 +1972,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr return mod.fail(&block.base, dest_ty_src, "expected enum, found {}", .{dest_ty}); } - if (!dest_ty.isExhaustiveEnum()) { + if (dest_ty.isNonexhaustiveEnum()) { if (operand.value()) |int_val| { return mod.constInst(arena, src, .{ .ty = dest_ty, @@ -2762,7 +2762,7 @@ fn analyzeSwitch( const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = src_node_offset }; // Validate usage of '_' prongs. - if (special_prong == .under and !operand.ty.isExhaustiveEnum()) { + if (special_prong == .under and !operand.ty.isNonexhaustiveEnum()) { const msg = msg: { const msg = try mod.errMsg( &block.base, diff --git a/src/type.zig b/src/type.zig index 1e52d2eb74..ab31991c36 100644 --- a/src/type.zig +++ b/src/type.zig @@ -2119,9 +2119,9 @@ pub const Type = extern union { } } - pub fn isExhaustiveEnum(ty: Type) bool { + pub fn isNonexhaustiveEnum(ty: Type) bool { return switch (ty.tag()) { - .enum_full, .enum_simple => true, + .enum_nonexhaustive => true, else => false, }; } diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index 3cf95ab6d6..1f590e2c47 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -717,6 +717,52 @@ pub fn addCases(ctx: *TestContext) !void { ":4:5: note: unhandled enumeration value: 'b'", ":1:11: note: enum 'E' declared here", }); + + case.addError( + \\const E = enum { a, b, c }; + \\export fn foo() void { + \\ var x: E = .a; + \\ switch (x) { + \\ .a => {}, + \\ .b => {}, + \\ .b => {}, + \\ .c => {}, + \\ } + \\} + , &.{ + ":7:10: error: duplicate switch value", + ":6:10: note: previous value here", + }); + + case.addError( + \\const E = enum { a, b, c }; + \\export fn foo() void { + \\ var x: E = .a; + \\ switch (x) { + \\ .a => {}, + \\ .b => {}, + \\ .c => {}, + \\ else => {}, + \\ } + \\} + , &.{ + ":8:14: error: unreachable else prong; all cases already handled", + }); + + case.addError( + \\const E = enum { a, b, c }; + \\export fn foo() void { + \\ var x: E = .a; + \\ switch (x) { + \\ .a => {}, + \\ .b => {}, + \\ _ => {}, + \\ } + \\} + , &.{ + ":4:5: error: '_' prong only allowed when switching on non-exhaustive enums", + ":7:11: note: '_' prong here", + }); } ctx.c("empty start function", linux_x64,