The ? operator
Writing a match for every Result gets long. The ? operator does the common case in one character.
?
Put ? after a Result:
- If it is
Ok(v), you getvand the code keeps going. - If it is
Err(e), the function returnsErr(e)right away.
use std::num::ParseIntError;fn double(s: &str) -> Result<i32, ParseIntError> { let n = s.parse::<i32>()?; Ok(n * 2)}ParseIntError is the error type that parse gives for numbers. It lives at std::num::ParseIntError, so the use line brings it in.
double("21") gives Ok(42). double("x") returns the parse error, and the Ok(n * 2) line never runs. To call a function and ignore the Result it gives back, write let _ = double("x");.
? on Option
? works on Option too, inside a function that returns Option. On None, the function returns None early.
fn second(v: &[i32]) -> Option<i32> { let x = v.get(1)?; Some(*x * 10)}Where ? works
? may return early, so the function's return type must be able to hold what it returns.
?on aResultneeds a function that returns aResultwith a fitting error type.?on anOptionneeds a function that returns anOption.- In a function that returns
()ori32,?is error E0277.
main can return Result
A plain fn main() returns (), so ? is not allowed there. Give main a Result return type and end it with Ok(()):
use std::num::ParseIntError;fn main() -> Result<(), ParseIntError> { let n: i32 = "4".parse()?; println!("{n}"); Ok(())}If main returns an Err, Rust prints the error and the program exits with a failure code.
Remember
?unwrapsOkor returns theErrearly.- On
Option,?unwrapsSomeor returnsNone. ?only works when the function returns a matching type (E0277).fn main() -> Result<(), E>lets you use?inmain.