There are two types of errors in rust, recoverable errors and unrecoverable errors.
To proprogate and error, return the error.
?
operatorThe ?
operator can be used to immediately return an error from a function! The ?
operator is only valid with functions that return Result
or Option
(or any type that implements Try
). Example:
use std::fs::File;
use std::io;
use std::io::Read;
fn read_from_file(f_name: &str) -> Result<String, io::Error> {
let f = File::open(f_name);
let mut opened_file = match f {
Ok(file) => file,
Err(e) => return Err(e),
};
let mut s = String::new();
match opened_file.read_to_string(&mut s) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}
}
fn shortcut_read_from_file(f_name: &str) -> Result<String, io::Error> {
let mut f = File::open(f_name)?; // Return Err if error occurred
let mut s = String::new();
f.read_to_string(&mut s)?; // Return Err if error occurred
Ok(s)
}
fn super_short_read_from_file(f_name: &str) -> Result<String, io::Error> {
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?;
Ok(s)
}
use std::fs;
fn the_shortest_read_from_file(f_name: &str) -> Result<String, io::Error> {
fs::read_to_string(f_name)
}
fn main() {
let f_name = String::from("file.txt");
let s1 = read_from_file(&f_name).unwrap();
println!("{}", s1);
}
Rust uses a Result<T, E>
enum to catch errors. Functions that have the possibility of erroring returns the Result
type. Example:
use std::fs::File;
use std::io::ErrorKind;
fn main() {
let f = File::open("file.txt");
let f = match f {
Ok(file) => file, // Return the file
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("file.txt") {
Ok(fc) => fc,
Err(e) => panic!("Cannot create the file: {:?}", e),
},
other_error => {
panic!("Problem opening the file: {:?}", other_error)
}
},
};
}
unwrap
can be used as a short cut if you want to panic!
on error. If an Ok
is returned, then unwrap
will return the value inside of the OK
.
let f = File::open("file.txt").unwrap();
Like unwrap
but executes closure if error occured.
let f = File::open("file.txt").unwrap_or_else(|err| {
println!("Error: {}", err);
// Do something else
});
Similar to unwrap
, expect
can be used to give your own error message in the case of an error.
let f = File::open("file.txt").expect("Failed to open file.txt");
Returns true if an error occurred:
let debug: bool = env::var("DEBUG").is_err();
panic!
is how to raise an unrecoverable error.
By default, when a panic occurs, the program starts unwinding by walking up the stack and cleaning up the data for each function. Alternatively, you can abort, which ends the program without cleaning up. Aborting leads to a smaller binary.
In order to make panics abort instead of unwind in production code (to create smaller binaries), you must add the following to your Cargo.toml
file:
[profile.release]
panic = 'abort'
Rust provides backtracing. To use do:
$ RUST_BACKTRACE=1 cargo run