Use `?` when a function can pass a failure to its caller rather than handle it immediately. It replaces repetitive or deeply nested matches: a successful `Result` yields its value, while an `Err` returns early. With `Option`, a present value continues and `None` returns early. The enclosing function must return a compatible `Result` or `Option`. section 3.1.2 section 4.5
Write a file without nested matches
```rust fn write_to_file() -> std::io::Result<()> { use std::fs::File; use std::io::prelude::*; let mut file = File::create("filename")?; file.write_all(b"File contents")?; Ok(()) } ``` If creating the file fails, writing never starts. If writing fails, that error returns instead. Only two successful calls reach `Ok(())`. The caller can still match on the returned result to print a success or failure message. section 3.1.2
When chained calls have different error types, the enclosing function’s error type must accept them. Implement `From` for the conversion: `impl From<std::io::Error> for ErrorWrapper` lets a function returning `Result<(), ErrorWrapper>` use `?` on file operations. Alternatively, `map_err()` changes a `Result` error explicitly. To cross between `Result` and `Option`, consider `ok()`, `err()`, or `ok_or()`; choose deliberately what information the conversion keeps. section 3.1.2
Listing 4.11 Reading the nth line from a file
use std::path::Path;
#[derive(Debug)]
pub enum Error { #1
Io(std::io::Error), #2
BadLineArgument(usize), #3
}
impl From<std::io::Error> for Error { #4
fn from(error: std::io::Error) -> Self {
Self::Io(error)
}
}
fn read_nth_line(path: &Path, n: usize) -> Result<String, Error> {
use std::fs::File;
use std::io::{BufRead, BufReader};
let file = File::open(path)?; #5
let mut reader_lines = BufReader::new(file).lines(); #6
reader_lines
.nth(n - 1) #7
.map(|result| result.map_err(|err| err.into())) #8
.unwrap_or_else(|| Err(Error::BadLineArgument(n))) #9
}
Opening the file uses `?` to propagate an I/O error through a custom error type. Selecting the requested line needs separate handling: the line may be absent, or reading it may fail. `?` does not replace those decisions. section 4.5
Prefer an explicit match or other control flow when failure calls for an action here rather than at the caller. `?` is also a safer default than `unwrap()` when failure should propagate instead of causing a panic. Use `expect()` with a useful message when exiting on failure is genuinely the intended behavior. section 4.5 section 10.3



