authorgravatar for justus@klausecker.deJustus Klausecker <justus@klausecker.de> 2026-07-24 16:50:07+02:00
committergravatar for justus@klausecker.deJustus Klausecker <justus@klausecker.de> 2026-07-24 17:48:10+02:00
logd3056114f6f17bb4723cccfa4dd578ddafb909a9
tree7a4d656adc0a413b83dca60b5e94fcee19c41eaf
parent619e54c81382d849f0bfcbe7e5c38f9b34390639

Sema: disallow unreachable `else` prong for tagged unions with nonexhaustive tag types


2 files changed, 57 insertions(+), 1 deletions(-)

src/Sema.zig+1-1
...@@ -11375,7 +11375,7 @@ fn validateSwitchBlock(...@@ -11375,7 +11375,7 @@ fn validateSwitchBlock(
1137511375
11376 if (has_else) {11376 if (has_else) {
11377 if (all_tags_handled) {11377 if (all_tags_handled) {
11378 if (item_ty.isNonexhaustiveEnum(zcu)) {11378 if (operand_ty.isNonexhaustiveEnum(zcu)) {
11379 if (has_under) return sema.fail(11379 if (has_under) return sema.fail(
11380 block,11380 block,
11381 else_prong_src,11381 else_prong_src,
test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig created+56
...@@ -0,0 +1,56 @@
1const E = enum(u8) {
2 a,
3 b,
4 _,
5};
6const U = union(E) {
7 a,
8 b,
9};
10fn foo() U {
11 return undefined;
12}
13
14export fn entry1() void {
15 const u = foo();
16 switch (u) {
17 .a => {},
18 }
19}
20export fn entry2() void {
21 const u = foo();
22 switch (u) {
23 .a => {},
24 .b => {},
25 else => {},
26 }
27}
28export fn entry3() void {
29 const u = foo();
30 switch (u) {
31 .a => {},
32 .b => {},
33 _ => {},
34 }
35}
36export fn entry4() void {
37 const u = foo();
38 switch (u) {
39 .a => {},
40 else => {},
41 _ => {},
42 }
43}
44
45// error
46//
47// :16:5: error: switch must handle all possibilities
48// :3:5: note: unhandled enumeration value: 'b'
49// :1:11: note: enum 'tmp.E' declared here
50// :25:14: error: unreachable else prong; all cases already handled
51// :30:5: error: '_' prong only allowed when switching on non-exhaustive enums
52// :33:9: note: '_' prong here
53// :30:5: note: consider using 'else'
54// :38:5: error: '_' prong only allowed when switching on non-exhaustive enums
55// :41:9: note: '_' prong here
56// :38:5: note: consider using 'else'