A non-exhaustive enum is an enum that may have other unknown members.
This can help create APIs that may be extended in future. This sort of thing frequently comes up in data formats, network protocols, and even C APIs.
Possible syntax:
_ as a trailing field.Semantics:
enum(u5) { X, Y, Z, _ }_ when an enum is already "full" (e.g. if it's u2 and you specify 4 values followed by a _), then there is a compiler error.switch-ed on, an else clause is always required@intToEnum can never fail with has no tag matching integer valuebuiltin.Enum gains a new boolean field is_exhaustiveRelated
extern enums:
- Non-exhaustive: else prong always needed in switch.
@intToEnumcan't fail.
So #3909 solved a problem, but it also introduced a problem. And I do think that this proposal solves the new problem.
With this proposal accepted, extern enums can be annotated as exhaustive or non-exhaustive. translate-c will choose non-exhaustive to be safe.
One more part of the specification
void field types for all unnamed tag values.I also want to include an extra feature of switch to go along with this proposal. The problem is that when an else is required on a switch, the compile error that tells you about missing tag names is gone. However, programmers should still be able to opt-in to compile errors when new tag names are added to non-exhaustive enums. So I will propose that switch gains _ syntax, which does the following:
elseExample:
const E = enum {
a,
b,
_,
};
test "non-exhaustive switch" {
var e: E = .b;
switch (e) {
.a => {},
.b => {},
_ => {
// handle unnamed tag values
},
// no else required
// compile error will occur if another tag is added to E
}
switch (e) {
.a => {},
.b => {},
else => {}, // OK; no compile error if another tag is added to E
}
switch (e) { // error: switch not handling the tag `b`
.a => {},
_ => {},
}
switch (e) { // error: switch on non-exhaustive enum must include `else` or `_` prong
.a => {},
.b => {},
}
}
I want to note that there is a case when you would do _ => unreachable. This is when you have a non-exhaustive extern enum because it defines a C ABI, however you know at the switch site that the library will always be linked statically; never dynamically. This means that the value of the enum will never be unnamed, because if the static library was updated, then the zig code would be recompiled against the corresponding updated enum.
Related: #3991
Most helpful comment
3909 made all extern enums non-exhaustive. However, I don't think that should necessarily be how it is. Just because an enum is part of an ABI does not mean it is non-exhaustive. According to how the C ABI works, whether an enum is exhaustive or not is part of the documentation of the API.
So #3909 solved a problem, but it also introduced a problem. And I do think that this proposal solves the new problem.
With this proposal accepted, extern enums can be annotated as exhaustive or non-exhaustive. translate-c will choose non-exhaustive to be safe.
One more part of the specification
voidfield types for all unnamed tag values.I also want to include an extra feature of
switchto go along with this proposal. The problem is that when anelseis required on aswitch, the compile error that tells you about missing tag names is gone. However, programmers should still be able to opt-in to compile errors when new tag names are added to non-exhaustive enums. So I will propose thatswitchgains_syntax, which does the following:elseExample:
I want to note that there is a case when you would do
_ => unreachable. This is when you have a non-exhaustive extern enum because it defines a C ABI, however you know at the switch site that the library will always be linked statically; never dynamically. This means that the value of the enum will never be unnamed, because if the static library was updated, then the zig code would be recompiled against the corresponding updated enum.Related: #3991