Upfront warning: this code relies on capturing errdefer, and there’s an accepted proposal to remove it from the language
Justus’ sweet rewrite of the switch logic got merged and I think that’s an enabler for the following idiom:
const std = @import("std");
pub fn fails(fail: bool) !void {
return if (fail) error.SomeError else {};
}
pub fn main() !void {
var debug_allocator = std.heap.DebugAllocator(.{}){};
const gpa = debug_allocator.allocator();
const data = try gpa.alloc(u8, 1024);
defer gpa.free(data);
// Here we express that we disallow OOM errors going forward, but
// we do allow other errors to propagate. You can obviously
// add more prongs as needed.
// However, this feature may be removed: https://github.com/ziglang/zig/issues/23734
errdefer |err| {
switch (err) {
error.OutOfMemory => comptime unreachable,
inline else => {},
}
}
try fails(true);
}
This is a variation of errdefer comptime unreachable, but we get to cherry-pick which errors we want to block and allow. In this example, OOM can only happen above errdefer, but we allow other errors.
This won’t compile on 0.15.x due to 'error.OutOfMemory' not a member of destination error set, but it does compile on latest master after Justus’ improvements.
Anyway, I haven’t tested this in real-world code and capturing errdefer is slated for removal, but figured I’d mention it.