Zig: errdefer with unreachable should allow function type to not have an error union

Created on 12 Apr 2020  路  4Comments  路  Source: ziglang/zig

const std = @import("std");
const expect = std.testing.expect;

fn perform() void {
    errdefer |err| {
        std.debug.warn("an error occurred: {}\n", @errorName(err));
        std.process.exit(1);
    }
    _ = try std.math.add(u8, 255, 1);
}

pub fn main() void {
    perform();
}

Expected: compiles successfully

Actual:

./test2.zig:9:9: error: expected type 'void', found 'std.math.error:340:43'
    _ = try std.math.add(u8, 255, 1);
        ^
proposal

Most helpful comment

using errdefer for error handling seems like an antipattern. The main2 example dbandstra posted above more effectively communicates intent. errdefer is meant to be used to clean up while returning an error, not prevent returning an error.

it is currently a compile error to return from a defer, and it should stay that way. otherwise, you get into strange scenarios where your code executes multiple return statements that override each other.

All 4 comments

This would be really nice. Much better than having to do this:

fn main2() !void {
    // the real code
}

fn main() u8 {
    main2() catch |err| {
        std.debug.warn("{}\n", .{err});
        return 1;
    };
    return 0;
}

Would you also be allowed to call return in the errdefer block?

Would you also be allowed to call return in the errdefer block?

That's a good question. I worry that would start to get too edge-casey and complicated to reason about. For example, will the other defers above it run or not if you do that? Regardless of what Zig does, someone reading such code for the first time will not know the answer to this question.

You're right, it is pretty hard to think about. Maybe this pattern is mostly useful for the main function, in which case your example with std.process.exit would suffice.

using errdefer for error handling seems like an antipattern. The main2 example dbandstra posted above more effectively communicates intent. errdefer is meant to be used to clean up while returning an error, not prevent returning an error.

it is currently a compile error to return from a defer, and it should stay that way. otherwise, you get into strange scenarios where your code executes multiple return statements that override each other.

Was this page helpful?
0 / 5 - 0 ratings