(no title)
tiehuis | 7 years ago
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...
dbaupp|7 years ago
Yep, as a sibling points out, I was working with a long-ago version of Zig's error handling.