It's far from perfect. One of the biggest problems with Rust error handling is that if you want to have explicit error return types encoded in the type system you need to create ad hoc enums for each method that returns an error. If you only use a single error type for all functions you will inevitably have functions returning Results that contain error variants that the function will never actually return but still…
I'm just now learning Rust, as a long time C++'er, and this was the first part of my Rust journey where I thought to myself, "Boy, this really smells--this couldn't possibly be the idiomatic Rust Way to handle functions that can produce different types of errors. I must be doing something wrong!" For example, I have a function that takes an array of bytes, decodes it as UTF-8 to text, parses that text into an i32, an…
https://play.rust-lang.org/?version=stable&mode=debug&editio...
fn main() {
match process(&[0x34, 0x32]) {
Ok(n) => println!("{n} is the meaning of life"),
Err(e) => {
if e.is::() {
eprintln!("Failed to decode: {e}");
} else if e.is::() {
eprintln!("Failed to parse: {e}");
} else {
eprintln!("{e}");
}
}
}
}
fn process(bytes: &[u8]) -> Result> {
let s = std::str::from_utf8(bytes)?;
let n = s.parse()?;
if n > 10 {
return Err(format!("{n} is out of bounds").into())
}
Ok(n)
}
In library code though that would make it generally more difficult to use the library, so the enum approach is more idiomatic. Then that comes out as match(e) {
MyError::Decode(e) => { ... }
MyError::ParseInt(e) => { ... }
...
}
etc, which is isomorphic to the style you miss. What you're perhaps missing the is that `except ...` is the just a language keyword to match on types, but that Rust prefers to encode type information as values, so that keyword just isn't needed.I feel you on the larval stage. Once you get past that, Rust starts to make a lot of sense.