Performant Software Systems with Rust — Lecture 6
Two Kinds of Errors
Recoverable: just report the problem to the user and retry the operation
File not found
Unrecoverable: Runtime bugs, need to terminate immediately
Learn more: Error Handling
Rust Does Not Use Exceptions
Exceptions in most other languages handle both kinds of errors the same way, using exceptions
But our code typically has a lot more recoverable errors that should be handled in a better, more graceful, way
For unrecoverable errors, we (or the Rust runtime) can just panic!
, causing a runtime crash immediately
Learn more: Error Handling
Panic!
Caused by
Taking an action, such as accessing a collection past its end, that causes the code to panic
Calling panic!
macro directly
Prints a message, walks back the stack and cleans up the data from each function, and quits
RUST_BACKTRACE=1 cargo run
Live Demo
Learn more: Unrecoverable Errors with panic!
Recoverable Errors with Result
where T
and E
are generic type parameters
Example: Opening a File
use std::fs::File;
fn main() {
// File::open returns `Result<T, E>`, where `T` is `std::fs::file`,
// the file handle, and E is `std::io::Error`
let greeting_file_result = File::open("llms.txt");
let greeting_file = match greeting_file_result {
Ok(file) => file,
Err(error) => panic!("Problem opening the file: {error:?}"),
};
}
Live Demo
Learn more: Recoverable Errors with Result
Shortcuts for Panic on Error: unwrap
Learn more: Shortcuts for Panic on Error: unwrap
and expect
Shortcuts for Panic on Error: expect
Learn more: Shortcuts for Panic on Error: unwrap
and expect
Propagating Errors
A function runs into an error
Instead of handling the error by itself, the function returns the error to the caller for it to decide what to do
use std::fs::File;
use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let username_file_result = File::open("llms.txt");
let mut username_file = match username_file_result {
Ok(file) => file,
Err(e) => return Err(e),
};
let mut username = String::new();
match username_file.read_to_string(&mut username) {
Ok(_) => Ok(username),
Err(e) => Err(e),
}
}
Learn more: Propagating Errors
The ?
Operator
Learn more: Propagating Errors: the ?
Operator
The ?
Operator Also Works with Option<T>
Values
Learn more: Where The ?
Operator Can Be Used
main()
Can Also Return Result
Learn more: Where The ?
Operator Can Be Used
main()
Can Also Return Result
Learn more: Where The ?
Operator Can Be Used
When Should We panic!
?
panic!
— or unwrap()
and expect()
— when we
panic!
condition will not be validResult
for the caller to processLearn more: To panic!
or Not to panic!
Create Custom Types for Data Validation
Learn more: Creating Custom Types for Validation
Create Custom Types for Data Validation
Learn more: Creating Custom Types for Validation
The Rust Programming Language, Chapter 9