Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. panic!() / unwrap() / expect() — When to Use Each

panic!() / unwrap() / expect() — When to Use Each

In Rust, panic! immediately stops the program when an unrecoverable error occurs. On the other hand, unwrap() and expect() panic when an Option or Result is None or Err. Knowing when to use panics versus recoverable errors is essential.

Syntax

// panic!: Stops the program with an unrecoverable error.
panic!("A fatal error occurred");
panic!("Index {} is out of bounds", index);

// unwrap(): Panics if the value is None or Err.
let value = some_option.unwrap();
let result = some_result.unwrap();

// expect(): Panics with a custom message.
let value = some_option.expect("Config file not found");

// unreachable!(): Marks code that should never be reached.
unreachable!("This code should never be reached");

// todo!(): Placeholder for unimplemented code (compiles successfully).
todo!("This feature is not yet implemented");

// unimplemented!(): An alternative to todo!.
unimplemented!();

Panic-related Macros and Methods

Macro / MethodDescription
panic!("message")Explicitly triggers a panic. Use for unrecoverable errors.
unwrap()Extracts the value from Some(T) or Ok(T). Panics on None or Err.
expect("message")Same as unwrap(), but panics with a custom message.
unwrap_or(default)Returns a default value when the result is None or Err (no panic).
unwrap_or_else(|| ...)Returns the result of a closure when the value is None or Err.
unreachable!()Marks a code path that should never be executed. Panics if reached.
todo!()Placeholder for unimplemented code. Panics if executed.
assert!(condition)Panics if the condition is false. Used for tests and precondition checks.
assert_eq!(a, b)Panics if a != b.

Sample Code

fn divide(a: f64, b: f64) -> f64 {
    // Precondition check (invariant of internal logic).
    assert!(b != 0.0, "Divisor must not be zero");
    a / b
}

fn first_even(numbers: &[i32]) -> Option<i32> {
    numbers.iter().find(|&&x| x % 2 == 0).copied()
}

fn main() {
    // unwrap(): Use when you are certain the value exists.
    let v = vec![1, 2, 3];
    let first = v.first().unwrap();  // Safe because the Vec is clearly non-empty
    println!("first: {}", first);

    // expect(): Provides a clear error message on panic.
    let value: Option<i32> = Some(42);
    let n = value.expect("Value was not set");
    println!("n: {}", n);

    // unwrap_or(): Falls back to a default value (no panic).
    let none: Option<i32> = None;
    let safe = none.unwrap_or(0);
    println!("safe: {}", safe);

    // unwrap_or_else(): Dynamically generates a default value.
    let result: Result<i32, &str> = Err("error");
    let val = result.unwrap_or_else(|e| {
        println!("Error occurred: {}", e);
        -1
    });
    println!("val: {}", val);

    // Safe handling of Option (if let / ? operator is preferred).
    let numbers = vec![1, 3, 5, 4, 7];
    match first_even(&numbers) {
        Some(n) => println!("First even number: {}", n),
        None => println!("No even numbers found"),
    }

    // Verify a precondition with assert!.
    let result = divide(10.0, 2.0);
    println!("10 / 2 = {}", result);
    assert_eq!(result, 5.0);

    // Use todo! to mark unimplemented code (compiles as long as it is not called).
    #[allow(dead_code)]
    fn not_yet_implemented() -> i32 {
        todo!("Implement this later")
    }

    // Example of unreachable!.
    let x = 5;
    let label = match x % 3 {
        0 => "Multiple of 3",
        1 => "3n+1",
        2 => "3n+2",
        _ => unreachable!("Remainder must be 0, 1, or 2"),
    };
    println!("x={}: {}", x, label);
}

Notes

Guidelines for choosing between panics and recoverable errors: use panics for programming bugs (such as violated preconditions or unreachable code paths), and use Result or Option for errors caused by user input or external conditions.

In production code, avoid overusing unwrap(). Prefer the ? operator or pattern matching to handle errors. Using unwrap() is acceptable in prototypes or when the safety is obvious.

A panic terminates the current thread. If the main thread panics, the entire process exits. In concurrent code, be careful that an unexpected panic in one thread does not affect other threads.

For defining custom error types, see 'Custom Error Types / thiserror'.

If you find any errors or copyright issues, please .