Discarding errors I know will not occur

I am calling a function which I know will not return certain errors.

How can I discard these errors and return all others?

For example:

pub fn foo(num: u8) !void {
    if (num == 0) return error.InvalidParameter;

    if (detectSomethingBad()) return error.SomethingBad;
}

test foo {

    // This call is bad because it propagates error.InvalidParameter
    // even though I know it cannot occur.
    try foo(3);

    // This call is annoying because I may have many errors to handle
    // that all I want to do is just return them.
    // And it is prone to me having a typo in the
    // returned error and accidentally renaming an error.
    foo(3) catch |err| switch (err) {
        error.InvalidParameter => unreachable,
        error.SomethingBad => return error.SomethingBad,
    };
}

and the compiler is not smart enough to trim the error set in this case:

foo(3) catch |err| switch (err) {
        error.InvalidParameter => unreachable,
        else => return err,
    };

Found the answer in the language reference:

https://ziglang.org/documentation/master/#catch

 Finally, you may want to handle only some errors. For that, you can capture the unhandled errors in the else case, which now contains a narrower error set:
handle_some_error_scenarios.zig

fn doAnotherThing(str: []u8) error{InvalidChar}!void {
    if (parseU64(str, 10)) |number| {
        doSomethingWithNumber(number);
    } else |err| switch (err) {
        error.Overflow => {
            // handle overflow...
        },
        else => |leftover_err| return leftover_err,
    }
}

I needed to capture the error subset in the else clause and return the error subset.

6 Likes