Rust exception basic: There is no exception in Rust, and there are two kinds of errors: recoverable and unrecoverable errors, instead. For recoverable errors, Rust gives the type Result<T, E>
to it, and for unrecoverable errors, there is a panic!
macro.
Fatal errors cannot be recovered by the program itself so the whole program just panics. Whenever the panic!
macro executes, the program will leave an error message, unwind and clean up the stack, and then quit with error code. By default, when a panic occurs, the program starts to unwinding, which means Rust walks back up the stack and cleans up the data from each function it encounters. We can also just abort the program by adding panic = 'abort'
to the appropriate [profile]
sections in the Cargo.toml
file.
[profile.release]
panic = 'abort'
Most errors will not cause the entire program panic, so we might handle it or ignore it. We can use the enum called Result<T, E>
to achieve this.
enum Result<T, E> {
Ok(T),
Err(E),
}
Here, T
represents the type of the value that will be returned in a success case within the Ok
variant, and E
represents the type of the error that will be returned in a failure case within the Err
variant. Because Result
has these generic type parameters, we can use the Result
type and the functions defined on it in many different situations where the successful value and error value we want to return may differ.
use std::fs::File;
let mut f = File::open("./data/input.txt");
// What if the file does not exist? The program has bug.
do_something_with_f(&mut f);
So the correct way to read the file should be as follows.
use std::fs::File;
let mut f = match File::open("./data/input.txt") {
Ok(file) => file,
Err(err) => println!("{:?}", err);
// Or panic.
}
Sometimes we need to execute different code snippets to handle different types of errors, and in this case we use std::io::ErrorKind
to do us this favor.
use std::io::ErrorKind;
// Code snippet from previous.
let mut f = match File::open("./data/input.txt") {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("./data/input.txt") {
Ok(file) => file,
Err(e) => panic!("{:?}", e),
},
other_error => {
panic!("Unknown error! {:?}", other_error)
}
},
};
unwrap
and expect
Using match
expression might be verbose, so we use a more concise method called unwrap
that automatically returns the value inside Ok
and calls panic!
if error happens. A very similar way is to use expect
which gives us the error message.