If a function returns an error union, Zig can infer the error set automatically. Does this also somehow work for functions that don’t return error unions, but just errors?
For example, is there a way to avoid having to explicitly specify the error{ A, B } error set here?
fn mapError(x: i32) error{ A, B } {
return if (x > 0) error.A else error.B;
}
!void or !noreturn is not the same though; with that I cannot return the result directly from a function that normally returns a different type, for example
fn caller(y: i32) error{ A, B }!i32 {
return if (y > 100) y else mapError(y);
}
(anyerror also wouldn’t work here, because “global error set cannot cast into a smaller set”.)
But with !noreturn at least it works when I call it with try, as return if (y > 100) y else try mapError(y);
You could use comptime to get the error type out of the return type from a function that returns !void. Though I wouldn’t do it. I’ve put in some compile logs that should help understand it. Have fun ;):
const std = @import("std");
fn ErrorReturnType(T: anytype) type {
const ti = @typeInfo(@TypeOf(T));
const return_type = @typeInfo(ti.@"fn".return_type.?);
const result = return_type.error_union.error_set;
// @compileLog(ti);
// @compileLog(return_type);
// @compileLog(result);
return result;
}
fn mapErrorInner(x: i32) !void {
return if (x > 0) error.A else error.B;
}
fn mapError(x: i32) ErrorReturnType(mapErrorInner) {
return if (mapErrorInner(x)) |_| unreachable else |err| err;
}
pub fn main() !void {
const a = mapErrorInner(1);
const b = mapError(0);
std.debug.print("{any} {any}\n", .{ a, b });
// @compileLog(a);
// @compileLog(b);
}