liveBook · Manning

Question mark operator

As explained in Learn Rust in a Month of Lunches

The question mark operator is Rust syntax that propagates an error from a Result or absence from an Option.

Put `?` after an expression that returns a `Result` when you want to pass an error back to the caller. With `Ok`, it gives you the value inside and continues. With `Err`, it returns the error immediately, so later lines do not run. It also works with `Option`: a value inside `Some` continues, while `None` returns early. section 6.2

Parse, then continue

In a function returning `Result<i32, ParseIntError>`, `let number = input.parse::<i32>()?;` gets the number if parsing succeeds. A following success message runs only in that case. Finish with `Ok(number)`: `?` gives you an `i32` on success, but the function still promises to return a `Result`. section 6.2

use std::num::ParseIntError;
 
fn parse_and_log_str(input: &str) -> Result<i32, ParseIntError> {
    let parsed_number = match input.parse::<i32>() {
        Ok(number) => number,
        Err(e) => return Err(e),
    };
    println!("Number parsed successfully into {parsed_number}");
    Ok(parsed_number)
}

Compare the longer `match` with `?`: its `Ok` arm takes the number, and its `Err` arm returns the error before printing the success message. section 6.2

The function using `?` must have a suitable return type. `main` can return `Result<(), ParseIntError>` when it uses `?` while parsing; if parsing fails inside a loop, it returns before reaching later items. When operations can produce different error types, choosing a shared error type needs more thought. One application returns `Result<(), Box<dyn Error>>`; another uses `anyhow::Error`. section 6.2 section 23.3.3 section 23.4.3

This is especially handy for file operations, where opening or reading may fail. It can also replace `.unwrap()` during cleanup when errors should be returned rather than cause a panic. In asynchronous code, error handling often appears as `.await?`. section 18.3 section 23.3.3 section 19.3.3

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains `Ok` and `Err` behavior through a worked parsing function and equivalent `match`, but defers combining different error types.
Examples
Shows string-to-integer parsing, a parsing loop that stops on error, and application refactoring that replaces `.unwrap()`.
What it assumes
Builds on familiarity with `Result`, `match`, and parsing, while explaining `?` and early return directly.
What you can do after
Practice/perform error propagation in Rust functions returning `Result`, including replacing `.unwrap()` with `?` where returning errors is appropriate.
How it connects
Connects `?` to `Result`, `Option`, `match`, early return, `.unwrap()`, and asynchronous `.await`.

Also explained in

Compare how 4 books explain question mark operator →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.