If you don't see std::result::Result as a core concept in Rust, which might be fair, one can still argue that it _should_ be a core concept, given its ubiquitous usage.
What I said is that “A function returns Result” in the universal sense (that is, everything that is a function returns Result) is not a core concept in Rust.
Some functions return Result<T,E> for some <T,E>. Some functions return Option<T> for some T. Some functions have no reason to use that kind of generic wrapper type (a pure function that handles any value in its range and returns a valid value in a simple type for each doesn't need either; Option/Result are typically needed with otherwise non-total functions or functions that perform side effects that can fail.)
I wouldn't use the emotionally-loaded dismissive language, but, yes, Result is a solution to the same problem as exceptions that deals with several problems of exceptions, including:
(1) Unchecked exceptions obscure what is going on, and frustrate analysis because things remote from the code may bypass it in the call-stack without any evidence visible in signatures.
(2) Checked exceptions are clear, but create a separate syntax for expressing type-like constraints, also limiting what you can do around them because they aren't the same thing as types.
Results are basically cleaner checked exceptions.
I love Rust to death, but I feel this is a huge flaw in its design. Writing any unsafe code that takes a callback function is a massive pain in the ass, because anytime you call this callback, it could panic, so you must restore into a safe state if stack unwinding occurs.
For example, I'm currently writing a fast sorting algorithm, using mostly unsafe code (by necessity). Every time I compare two elements, a panic could occur, and all elements have to be placed back in the input array to restore to a safe state. It's hellish.
There is the panic = abort flag which is great if you're writing a binary. But as a library you can not assume this.
IMO, one of the most valuable pieces of exception handling is a distinct separation between your error logic and your non-error logic, which makes methods easier to comprehend. I also feel like the existence of the ? syntax is a dead giveaway in this regard because it's a fig-leaf trying to cover up the most egregious parts of the code where you'd otherwise have to be write the frequent "if error then early return error" statements which plague Golang.
It avoids creating a separate syntax from the usual return-type declaration syntax for declaring the existence of errors, when compared to checked exceptions.
It also avoids creating a separate syntax for error handling, compared to (checked or unchecked) exceptions (pattern matching is ubiquitous in Rust for other purposes).
> It's created a different, more complex syntax which must be adopted inline in your actual normal code path, obfuscating what your code is actually expected to do under non-error conditions.
Pattern matching isn't an additional syntax (indeed, many languages with exceptions also have it), and it (IMO) does less to obscure non-error code than the visual noise of handling errors with try/catch.
It is more visual noise in the case of functions that do the equivalent of not handling exceptions, compared to exception-using langauges where that is implicit.
That is not, in fact, a core concept in Rust. Plenty of functions have no reason to return Result. (And some that do also have a reason for the inner class to be a result.)
> This concept in Rust is so ubiquitous that it should be a first class citizen. It should, under all circumstances, be syntactically implicit:
“Implicit” is an opposed concept to “first-class citizen”. Result is first-class in Rust, and would not be if function returns were implicitly Result.