That's a peculiar observation, it's like saying Rust's borrow checker is magical because it needs language-level support. I mean, that's the point.
In any case re: zig error or rust's Result, I don't think either of us are discussing features and pros/cons, but just describing what we like the best. Not very objective an argument.
> but since errors are literally just u16 they’re also deeply lacking in richness and composability
Zig errors are composable: https://ziglang.org/documentation/master/#Merging-Error-Sets and later sections.
You can’t do borrow checking without language support (I think, at least not without a significantly more expressive type system) whereas Result is pretty much just a type, the features it uses are mostly non-exclusive, and those which are, are very much intended not to remain so (e.g. the `Try` trait for the `?` operator).
> Zig errors are composable: https://ziglang.org/documentation/master/#Merging-Error-Sets and later sections.
Not really? That’s just merging error sets, but you can’t say that you’ve got an error which originally comes from an other error, except by creating its dual and documenting it as such. Essentially your choices are full transparency or full type erasure.
What you just described are error traces. They're generated by Zig auomatically for you, thanks also to the fact that errors are a special construct in the language.
Relevant langref passage:
https://ziglang.org/documentation/master/#Error-Return-Trace...
Sum types are a powerful language feature, but they’re also a general language feature, they don’t exist for the sole purpose of creating a Result type (and indeed a number of languages have had the former and lacked the latter).
And affine types are not here for borrow checking, it’s closer to the opposite. Affine types are a formalisation of RAII, borrow checking is a way to make references memory-safe without runtime overhead which mostly avoids unnecessary (and sometimes impossible requiring allocations & refcounting) copies of affine types.
From what I know of zig’s error handling, I really don’t think it’s better than result types.
It is less work, especially when using error unions (though I think that makes it easier to miss changes to error sets as they’re implicit), but since errors are literally just u16 they’re also deeply lacking in richness and composability.
It’s definitely an improvement over C’s error style, and thus perfectly understandable given zig’s goal, but I very much disagree that it’s “better than Result”.
It’s also extremely magical in that it needs special language-level support throughout in ways Result is not, but obviously that’s more of a matter of taste.