From d3056114f6f17bb4723cccfa4dd578ddafb909a9 Mon Sep 17 00:00:00 2001 From: Justus Klausecker Date: Fri, 24 Jul 2026 16:50:07 +0200 Subject: [PATCH] Sema: disallow unreachable `else` prong for tagged unions with nonexhaustive tag types --- src/Sema.zig | 2 +- ...n_with_nonexhaustive_tag_is_exhaustive.zig | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig diff --git a/src/Sema.zig b/src/Sema.zig index 6dafdeb0ee6c53fb6f116272e28c641239573cff..a52b11b506a71f7d4c4c734dbded00d5f5996a40 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -11375,7 +11375,7 @@ fn validateSwitchBlock( if (has_else) { if (all_tags_handled) { - if (item_ty.isNonexhaustiveEnum(zcu)) { + if (operand_ty.isNonexhaustiveEnum(zcu)) { if (has_under) return sema.fail( block, else_prong_src, diff --git a/test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig b/test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig new file mode 100644 index 0000000000000000000000000000000000000000..fc289fb55fb2c7fb0db1dd990fea16f431509595 --- /dev/null +++ b/test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig @@ -0,0 +1,56 @@ +const E = enum(u8) { + a, + b, + _, +}; +const U = union(E) { + a, + b, +}; +fn foo() U { + return undefined; +} + +export fn entry1() void { + const u = foo(); + switch (u) { + .a => {}, + } +} +export fn entry2() void { + const u = foo(); + switch (u) { + .a => {}, + .b => {}, + else => {}, + } +} +export fn entry3() void { + const u = foo(); + switch (u) { + .a => {}, + .b => {}, + _ => {}, + } +} +export fn entry4() void { + const u = foo(); + switch (u) { + .a => {}, + else => {}, + _ => {}, + } +} + +// error +// +// :16:5: error: switch must handle all possibilities +// :3:5: note: unhandled enumeration value: 'b' +// :1:11: note: enum 'tmp.E' declared here +// :25:14: error: unreachable else prong; all cases already handled +// :30:5: error: '_' prong only allowed when switching on non-exhaustive enums +// :33:9: note: '_' prong here +// :30:5: note: consider using 'else' +// :38:5: error: '_' prong only allowed when switching on non-exhaustive enums +// :41:9: note: '_' prong here +// :38:5: note: consider using 'else' -- 2.54.0