Although the compiler will implement default error handling, it is good to understand how to handle errors for custom logic. Error handling will prevent your program from returning undesired output or terminating abnormally.
Let us explore how to handle errors in the Rust programming language.
Rust Error Types
There are two types of errors in Rust:
- Recoverable Errors
- Unrecoverable Errors
Unrecoverable Errors
Unrecoverable errors refer to the types of errors that cause a program to die or exit abnormally. An example would be accessing an out-of-bound index in an array.
Rust uses the panic! macro to handle unrecoverable errors. Suppose the compiler encounters the panic! macro in your code. It prints the specified messages, cleans up the stack, and terminates the program.
The panic! macro is very useful when you encounter errors from which the program cannot recover.
Take a simple program provided below that illustrates how to use the panic macro:
panic!("I'm Dead!!");
}
Once you execute the previous code, you should get an output as shown below:
Calling panic! causes the program to exit and print the panic method specified.
Backtracing a Panic
Rust allows us to backtrace the source of error using the RUST_BACKTRACE environment variable. Backtracing refers to a list of functions that have been called before the error occurred.
Take the example provided below:
let vec = vec![1,2,3,4,5];
println!(“{}”, vec[5]);
}
In the previous example, we are attempting to read an out-of-bounds array index. This should cause the program to panic and exit.
An output example output is provided below:
As you can see from the output, the compiler tells us we can use the RUST_BACKTRACE environment variable to get the backtrace of the error.
We can do this using the following command:
This should return the backtrace output as:
This should return a detailed output of how the error happened in your code. For an entirely verbose option, you can use the RUST_BACKTRACE=full.
Recoverable Errors
Typically, you will rarely need to handle unrecoverable errors. To handle recoverable errors in Rust, we use the Result enum, which holds two variants: Ok and Err.
Let us take the following simple program attempting to open a file:
fnmain() {
let file = File::open("hello.txt");
println!("{:?}", file);
}
The previous code attempts to open a non-existent file. Running the program provided above should return as:
However, we can define the action we want if the file does not exist. An example is shown below:
fnmain() {
let file = File::open("hello.txt");
match file {
Ok(file) => {
println!("file found: {:?}", file)
},
Err(_error) => {
println!("file not found")
}
}
}
Here, we use the match operator to check if the file returned an error or Ok. Then, we take the actions for each case.
We can also use the expect method to create custom error handling specifics.
For example:
fnmain() {
let file = File::open("hello.txt")
.expect("Error occurred when reading file");
}
The expect method, which will call the panic macro in an error, is encountered when opening the file.
Closing
This tutorial covered the fundamentals of error handling in the Rust programming language. In addition, this guide discussed the two types of errors: recoverable errors and unrecoverable errors. We hope you found this article helpful. Check the other Linux Hint articles for more tips and information.