| Zig's errors are actually different and the variants can be statically
known. Error type returns are not usually specified since they can usually
be inferred. They can be explicitly specified if needed [1]. For example, the following code fn errorOrAdd(a: u8, b: u8) !u8 {
if (a == 2) return error.FirstArgumentIsTwo;
if (b == 2) return error.SecondArgumentIsTwo;
return a + b;
}
pub fn main() void {
if (errorOrAdd(0, 0)) |ok| {
} else |err| switch (err) {
// will force a compile-error to see what errors we haven't handled
}
}
emits this error at compile-time: /tmp/t.zig:13:18: error: error.SecondArgumentIsTwo not handled in switch
} else |err| switch (err) {
^
/tmp/t.zig:13:18: error: error.FirstArgumentIsTwo not handled in switch
} else |err| switch (err) {
^
You can use the global `error` type which encapsulates all other error types if needed,
replacing `errorOrAdd` in the previous `main` with the following function fn anyError() error!u8 {}
now requires an else case, since it can be any possible error. /tmp/t.zig:13:18: error: else prong required when switching on type 'error'
} else |err| switch (err) {
^
This works pretty well and is very informative in most cases. The tradeoffs
are it can make some instantiation of sub-types a bit clunky [2] and you need
to avoid the global error type everywhere. The global error infests all calling
functions and makes their error returns global as a result. You can however
catch this type and create a new specific variant so there is a way around this
for the caller at least.Do remember that Rust allows passing information in the Err variant of a Result
while Zig's error codes are just that, codes with no accompanying state. [1] https://github.com/tiehuis/zig-bn/blob/3d374cffb2536bce80453... [2] https://github.com/tiehuis/zig-deflate/blob/bb10ee1baacae83d... |
Yep, as a sibling points out, I was working with a long-ago version of Zig's error handling.