July 19, 2026, 1:26pm 1
const E = enum(u2) {
foo,
bar,
_,
};
const U = union(E) {
foo,
bar,
};
var v: U = .foo;
var e: E = .foo;
pub fn main() void {
// This one compiles.
switch (v) {
.foo => {},
.bar => {},
}
// This one also compiles.
switch (v) {
.foo => {},
.bar => {},
else => {},
}
// This one compiles, too.
switch (e) {
.foo => {},
.bar => {},
_ => {},
}
// This one fails to compile.
switch (v) {
.foo => {},
.bar => {},
_ => {}, // error
}
}
The compile error is
test.zig:38:5: error: '_' prong only allowed when switching on non-exhaustive enums
switch (v) {
^~~~~~
test.zig:41:9: note: '_' prong here
_ => {}, // error
^
test.zig:38:5: note: consider using 'else'
which, if anything, means that the behavior is completely intentional, as v is a union and not an enum.
The rationale, I believe, being that enums can be non-exhaustive, in which case the _ branch makes sense, but unions cannot.
zigo July 19, 2026, 1:40pm 3
I mean, are the inconsistencies intentional? And is it intentional to allow to use a non-exhaustive enum as union tag type?
Ah I see now, do you mean how the else branch is allowed when switching on the union even though all variants have been exhausted? Indeed this could be an oversight but I am not sure.
Checking into the compiler (around src/Sema.zig:11020), switching on unions is done through the backing enum, and since E is non-exhaustive, the else branch is allowed on v, but since _ is only allowed for non-exhaustive enums, the last example gets rejected.
It might be worth looking into the issues on codeberg (which it’s not letting me right now :^))
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.