authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-07 22:19:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-07 22:19:17-07:00
log57aa289fdef543a507d8da039f5b7e7f2762c878
tree1e8f3c072f2c004554880cd23e53337bbc24a39b
parente730172e47749db8a9d3be5949231bde95343b39

Sema: fix switch validation '_' prong on wrong type


3 files changed, 50 insertions(+), 4 deletions(-)

src/Sema.zig+2-2
......@@ -1972,7 +1972,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
19721972 return mod.fail(&block.base, dest_ty_src, "expected enum, found {}", .{dest_ty});
19731973 }
19741974
1975 if (!dest_ty.isExhaustiveEnum()) {
1975 if (dest_ty.isNonexhaustiveEnum()) {
19761976 if (operand.value()) |int_val| {
19771977 return mod.constInst(arena, src, .{
19781978 .ty = dest_ty,
......@@ -2762,7 +2762,7 @@ fn analyzeSwitch(
27622762 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = src_node_offset };
27632763
27642764 // Validate usage of '_' prongs.
2765 if (special_prong == .under and !operand.ty.isExhaustiveEnum()) {
2765 if (special_prong == .under and !operand.ty.isNonexhaustiveEnum()) {
27662766 const msg = msg: {
27672767 const msg = try mod.errMsg(
27682768 &block.base,
src/type.zig+2-2
......@@ -2119,9 +2119,9 @@ pub const Type = extern union {
21192119 }
21202120 }
21212121
2122 pub fn isExhaustiveEnum(ty: Type) bool {
2122 pub fn isNonexhaustiveEnum(ty: Type) bool {
21232123 return switch (ty.tag()) {
2124 .enum_full, .enum_simple => true,
2124 .enum_nonexhaustive => true,
21252125 else => false,
21262126 };
21272127 }
test/stage2/cbe.zig+46
......@@ -717,6 +717,52 @@ pub fn addCases(ctx: *TestContext) !void {
717717 ":4:5: note: unhandled enumeration value: 'b'",
718718 ":1:11: note: enum 'E' declared here",
719719 });
720
721 case.addError(
722 \\const E = enum { a, b, c };
723 \\export fn foo() void {
724 \\ var x: E = .a;
725 \\ switch (x) {
726 \\ .a => {},
727 \\ .b => {},
728 \\ .b => {},
729 \\ .c => {},
730 \\ }
731 \\}
732 , &.{
733 ":7:10: error: duplicate switch value",
734 ":6:10: note: previous value here",
735 });
736
737 case.addError(
738 \\const E = enum { a, b, c };
739 \\export fn foo() void {
740 \\ var x: E = .a;
741 \\ switch (x) {
742 \\ .a => {},
743 \\ .b => {},
744 \\ .c => {},
745 \\ else => {},
746 \\ }
747 \\}
748 , &.{
749 ":8:14: error: unreachable else prong; all cases already handled",
750 });
751
752 case.addError(
753 \\const E = enum { a, b, c };
754 \\export fn foo() void {
755 \\ var x: E = .a;
756 \\ switch (x) {
757 \\ .a => {},
758 \\ .b => {},
759 \\ _ => {},
760 \\ }
761 \\}
762 , &.{
763 ":4:5: error: '_' prong only allowed when switching on non-exhaustive enums",
764 ":7:11: note: '_' prong here",
765 });
720766 }
721767
722768 ctx.c("empty start function", linux_x64,