A panic signals that execution should not continue normally. Use panic! when an assumption has been violated or an error is unrecoverable. It unwinds the current thread’s stack; a panic in the only main thread exits the program with an error, while a panic in a background thread exits that thread. section 2.5.6
A failing operation need not cause a panic. Rust’s Result holds either a success value or an error value. A caller can handle the error, retry, or return it with ?. Choose a panic when the caller should not continue rather than as the default response to every error. section 2.5.6 section 2.6
Three ways to panic when a Result contains an error:
- Match the Err variant and call panic! with a message specific to the failure. section 2.5.6
- Call .unwrap() to use the success value or panic on an error. The error type must support Debug so the panic can display it. section 2.5.6
- Call .expect("context") for the same choice with a message that identifies what failed. section 2.5.6
A negative FizzBuzz input
If fizzbuzz(-1) returns Err(Error::GotNegative), print_fizzbuzz can match that error and panic with the input value. Replacing the match with fizzbuzz(x).unwrap() is shorter, but requires Error to derive Debug and reports the error value instead of the tailored message. .expect("Failed to run fizzbuzz") adds context without restoring the match. section 2.5.6
Listing 2.37 Panicking when print_fizzbuzz sees an error
enum FizzBuzzValue {
Fizz,
Buzz,
FizzBuzz,
NotDivisible(i32),
}
enum Error {
GotNegative,
}
fn main() {
print_fizzbuzz(-1); #1
}
fn print_fizzbuzz(x: i32) { #2
match fizzbuzz(x) {
Ok(result) => match result {
FizzBuzzValue::FizzBuzz => {
println!("FizzBuzz");
}
FizzBuzzValue::Fizz => {
println!("Fizz");
}
FizzBuzzValue::Buzz => {
println!("Buzz");
}
FizzBuzzValue::NotDivisible(num) => {
println!("{}", num);
}
#3
},
Err(Error::GotNegative) => {
panic!("Got a negative number for fizzbuzz: {}", x);
}
}
}
fn fizzbuzz(x: i32) -> Result<FizzBuzzValue, Error> {
if x < 0 {
Err(Error::GotNegative)
} else if x % 3 == 0 && x % 5 == 0 {
Ok(FizzBuzzValue::FizzBuzz)
} else if x % 3 == 0 {
Ok(FizzBuzzValue::Fizz)
} else if x % 5 == 0 {
Ok(FizzBuzzValue::Buzz)
} else {
Ok(FizzBuzzValue::NotDivisible(x))
}
}
The full FizzBuzz listing shows the explicit Err branch that calls panic! instead of returning an error. section 2.5.6
A panic message identifies where the panic occurred. Set RUST_BACKTRACE=1 when running the program to see the call stack; backtraces are not shown by default. In tests, assert! and assert_eq! panic on failed checks, and the test framework catches the panic and marks that test as failed. .unwrap() and .expect() can likewise make a test fail when an operation returns an error. section 2.5.6 section 7.1







