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... )