DEV Community

Discussion on: Error Handling in Rust programming language

 
genbattle profile image
Nick Sarten • Edited

Code like this looks super messy to me:

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("hello.txt");

    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut s = String::new();

    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

Rust has a solution to this, the ? operator. It used to be a macro back in the early days, but it basically means: give me the value here if everything's ok, or return the error if not.

So your example becomes:

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("hello.txt");
    let mut s = String::new();

    f?.read_to_string(&mut s)?
    Ok(s)
}

The overhead here is similar to exceptions with better enforcement around handling. This is a massive improvement on C-style error return values.

Thread Thread
 
aminmansuri profile image
hidden_dude

Thanks Nick.

That makes a bit more sense to me. I'm not convinced that its better than Exceptions (though I never really loved Exceptions either).. but you're right that this makes it much better than the old C way. My only problem is that if you forget a little '?' somewhere you don't get proper error handling. Exceptions aren't as brittle.

In C we used to write macros to accomplish such things but of course they are more verbose.

Thread Thread
 
genbattle profile image
Nick Sarten • Edited

Most of the time if you forget a ? somewhere then your program won't compile, because you'll have an Option/Result, not the value you're expecting in a given expression.

You're correct though that there's a hole where functions return Result<(), Error> because you can ignore the return value without getting an error, however the Rust compiler will spit out a warning for an unused Result:

warning: unused `std::result::Result` that must be used
 --> src/lib.rs:9:5
  |
9 |     f?.read_to_string(&mut s);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_must_use)] on by default
  = note: this `Result` may be an `Err` variant, which should be handled

So while I agree that Rust isn't head and shoulders better than C++ in every way, I think error handling is currently one area where Rust has a significant advantage.

Thread Thread
 
aminmansuri profile image
hidden_dude

thanks for the info Nick.