> It's still under debate and I'm personally in the camp that errors should not have a payload, so I would avoid assuming that it's definitely the preferable choice.
How can you argue that not having access to string index where the JSON was unparseable is better than having access to it? I read through issues/2647, and I read through the "existing pattern", and it just seems obvious to me that containing the error information in the error is better than trying to hack it through side channels.
If A -> B, and B returns an error through a side channel, then A can use it and "what's so bad about that?"
But this doesn't seem to scale very well.
If A is refactored to use an intermediate function X, then it just doesn't work. A -> X -> C would mean that...
X cannot use Zig's normal error handling syntax to automatically propagate this error that A is better equipped to handle, unless we're going to further stipulate that A must pass this Diagnostics struct into X which then must pass it into B.
If we now assume that X calls into two fallible functions, B and C, and each of them provide their own diagnostics structs, then X will have to take in two "out" arguments that provide the diagnostics, and every single caller of X will have to provide those two values.
You see how this goes. It just doesn't seem scalable.
Why not take the current design to its logical conclusion of simply having every function return a Boolean indicating whether it succeeded or not, and then require the caller to look into some "out" argument to determine what the error was? Obviously, that would be extremely annoying.
A tagged error union containing the diagnostic error values is just a minor evolution of the current design that brings huge wins for language ergonomics.
For errors that don't need to carry a value, there is no additional cost: they compile and work exactly as they do today.
For errors that carry a value, the size of the error struct is only the size of the largest error value (plus the tag, of course), not the product of all possible error values, so the global error set will never grow to be enormous unless you have some very weird error type. In which case, you can solve this problem by fixing that error type.
So, I'm not deeply versed in Zig, but I have personally argued in favor of Zig's async design, which seems exceptionally interesting. I had not realized until now how limiting the error system implementation was, but I had superficially appreciated how much less verbose it was than Rust's where you tend to hand write these error enums, or use a bunch of code gen. However, errors benefit tremendously from having the ability to supply payloads.
No one is required to act on the payloads within the errors, but no one is able to if they don't exist.