See this example:
fn foo() error{Fail}!void {
return error.Fail;
}
pub fn main() void {
if (foo() == error.Pineapple) {
// 😱
}
}
Although foo
returns a specific error set, ==
doesn’t check that the literal on the right is a member of it.
Feels error prone!
Hat tip to The unexpected productivity boost of Rust
6 Likes
Sze
August 27, 2025, 5:16pm
2
But could it be made into a compile error?
It seems like it could be.
2 Likes
error.
can refer to any error. If the compiler had never seen that error before, it introduces it at that point. So I don’t think it can be made a compiler error.
Instead, I suggest always defining an error set for all errors you are working with, and rigorously reference your errors through your set:
const FooError = error{Fail};
fn foo() FooError!void {
return FooError.Fail;
}
pub fn main() void {
// Now this is a compiler error
if (foo() == FooError.Pineapple) {
// 😀
}
}
5 Likes
matklad:
foo() == error.Pineapple
It’s news to me that this is a valid way of handling a possible error, so I went back and tried older versions to see if this was always the case.
In the stage1 (C++) compiler, this was an error:
./eql-catch.zig:8:15: error: operator not allowed for type 'error{Fail,Pineapple}!void'
if (foo() == error.Pineapple) {
So I’d honestly consider this a self-hosted compiler regression, unless it’s truly intentional that an error union can be compared using ==
.
1 Like
Nevermind, it was fully intentional:
opened 06:20PM - 29 Jul 18 UTC
closed 09:26PM - 10 Oct 22 UTC
proposal
accepted
Edit: oops, I thought I was in the search UI.
```zig
const assert = @import(… "std").debug.assert;
test "aoeu" {
assert(foo() == error.Bad);
assert(bar() == error.Bad);
}
fn foo() error {
return error.Bad;
}
fn bar() error!void {
return error.Bad;
}
```
I don’t quite understand the use-case, though.
Comparing errors with ==
seems fine, but upcasting a specific error union to anyerror feels like a bug.
3 Likes
yes looking at the proposal issue it doesn’t seem to state that the upcasting is intentionally wanted