Disallowing auto-typing of error-union

A very common mistake that programmers may make while programming in Zig is forgetting to use try:


fn foo(b: bool) !i32 {
    return if (b) 123 else error.TheWorldHatesFalseBecauseOfTruism;
}

pub fn main() void {
    const num = foo();
    std.debug.print("foo() => {d}\n", .{num});
}

Easy error to fix but really annoying, as the error message is usually hard to decipher because @typeName() of an error set is often very, very long. And if the variable in question gets passed to a function accepting anytype, you could end up with an error triggered at a location far from where the omission of try actually is.

Since we almost never store error unions in variables, I think it’d be helpful to not allow their creation without an explicitly declared type. Detecting omissions of try during syntax highlighting would save a lot of time.

I see the point, but I have a few concerns:

  1. For the cases where you do want to hold the error union object, it’s not always trivial to write its type.
  2. it could make generic programming more complicated. I’m assuming there are cases where the generic code doesn’t care if an expression is an error union, a normal value, or even void.

Should we also disallow sending an error union value into an anytype argument?

3 Likes

Getting the type will be easy if/when type capturing is implemented:

    const value: |T| = foo();

Thinking of the situation of in terms of type capturing, the following:

    const value = foo(); 

is equivalent to:

    const value: |_| = foo();

Since the language does not allow discarding of an error union, it shouldn’t allow discarding of an error union type either.

If you’re writing code that handles every type, you almost certainly would need to know the type anyway, so forcing the capture isn’t really a burden.