I tried Rust for the first time a few months ago. One of the things that really impressed me was that it was very easy to just get started. Even though the language is very different than I'm used to, I was able to "just jump in" without jumping through a lot of hoops. I was working with 3rd party crates very quickly.
One thing that I think does need improvement is the error handling. Far too many idiomatic examples just panic for error handling. There's no good way to just group errors by a higher-level classification and fall through to a generic error handler. As a result, the choice is between panic on error, or very detailed and verbose error handling. There's no middle ground.
The From is The Right Thing, but it can be hard to convince people used to unchecked exceptions and costless casting of this. (I say costless, you pay for it every time you don't cast...)
For error handling, I'd encourage you to look at error-chain. It makes it pretty simple to propagate all your errors with try!/? so long as all your functions return a Result. And the quick_main macro can handle the panicking if you let it propagate all the way to main. Hopefully once the ? In main RFC gets released, quick_main won't even be necessary.
There's a couple of annoyances to it. The documentation is really sparse for something as integral as it aims to be. And there's a frustratingly large number of third-party crates that don't use standard error types and prevent you from calling chain_error to convert from their error types to yours.
But once you get the gist of it, a few lines of boilerplate gives you the ability to handle errors concisely and correctly throughout your program.
There actually is a way to do that, which is to return Results, with error types that implement From so the nested errors can be "wrapped" in the generic ones, and then you can just use the ? postfix operator as an alternative to unwrapping in order to bubble up the errors.
If you're designing your own errors then there's some boilerplate you need to allow for the error wrapping, though you can always take the cheap way out and use Box<Error> as your error type (as any error can be wrapped in that).
Most of the replies pointed out the new ? operator, which I'll have to check out. (One of the things that I like about the Rust community is that they constantly improve.)
The thing is, if you've only handled errors via return codes in C, then Rust's system is a major improvement. The challenge comes once you've programmed with exceptions that have inheritance. It's pretty easy to set filters higher up in the stack and "not care" lower in the stack. This allows you to effectively ignore error handling for functions that only fail in obscure corner cases, because a filter higher up in the stack can handle so many different errors. (Operations that require cleanup can also be written in a way that cleanup code always runs, as some languages support try-finally.)
That's probably the hardest thing for me to adjust to in Rust. Lifetimes take care of the try-finally part, but I still can't figure out how to have generic error filters higher in my stack.
Existing error handling facilities in Rust may not suit every use-case. For me personally, the difficulty with the `?` operator (and try! macro) is that the File + Line info about the source of error is lost. Also, I want something simpler than the approach taken by the `error-chain` crate. My current solution is to use some custom macros to check for errors and display an execution trace (example here: https://play.rust-lang.org/?gist=a7fb903ce2bbb37914ab380d342... )
I was thinking the same as you until I learned about Result<(), Box<Error>>.
It’s super quick and not really that far off from the detailed hand-roll solution.
One thing that I think does need improvement is the error handling. Far too many idiomatic examples just panic for error handling. There's no good way to just group errors by a higher-level classification and fall through to a generic error handler. As a result, the choice is between panic on error, or very detailed and verbose error handling. There's no middle ground.