← Back to Rust Course | Chapter 10: Error Handling | Lesson 2 of 6

The ? Operator

The ? mark is a shortcut that says "if this failed, stop here and hand the failure up to whoever called me."

Basic Use of the ? Operator

Placing ? after an expression that returns Result unwraps the Ok value automatically, or immediately returns the Err from the enclosing function if it failed.

Example: Basic Use of the ? Operator

markup
fn parse_number(s: &str) -> Result<i32, std::num::ParseIntError> {
    let n = s.parse::<i32>()?;
    Ok(n * 2)
}

fn main() {
    match parse_number("21") {
        Ok(v) => println!("Doubled: {}", v),
        Err(e) => println!("Error: {:?}", e),
    }
}

Chaining Multiple Fallible Calls

The ? operator shines when chaining several fallible operations, letting each step propagate its error immediately instead of requiring a nested match for every call.

Example: Chaining Multiple Fallible Calls

markup
fn parse_and_add(a: &str, b: &str) -> Result<i32, std::num::ParseIntError> {
    let x = a.parse::<i32>()?;
    let y = b.parse::<i32>()?;
    Ok(x + y)
}

fn main() {
    println!("{:?}", parse_and_add("3", "4"));
}

The Enclosing Function Must Return a Compatible Type

? can only be used inside a function whose return type is itself a Result (or Option) with a compatible error type, since it needs somewhere to return the propagated error to.

Example: The Enclosing Function Must Return a Compatible Type

markup
fn compute(input: &str) -> Result<i32, std::num::ParseIntError> {
    let value: i32 = input.parse()?;
    Ok(value + 100)
}

fn main() {
    println!("{:?}", compute("5"));
    println!("{:?}", compute("oops"));
}

Using ? with Option

The ? operator also works on Option, returning None early from the function if the value is None, mirroring how it works with Result.

Example: Using ? with Option

markup
fn first_char_uppercase(s: &str) -> Option<char> {
    let c = s.chars().next()?;
    Some(c.to_ascii_uppercase())
}

fn main() {
    println!("{:?}", first_char_uppercase("rust"));
    println!("{:?}", first_char_uppercase(""));
}
Common Mistakes
  1. Using ? inside a function whose return type is not Result (or Option), which fails to compile.
  2. Forgetting ? only propagates the error -- it does not itself print anything or crash the program.
  3. Mixing incompatible error types across multiple ? calls without a conversion, which the compiler will reject unless the types unify.
Chapter Summary
  • ? after a Result-returning expression unwraps Ok values or returns early with the Err.
  • The enclosing function must itself return a compatible Result (or Option) type for ? to be used.
  • ? dramatically reduces boilerplate compared to manually matching every fallible call.
  • ? can also be used with Option, returning None early if the value is None.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.