The ? Operator
? mark is a shortcut that says "if this failed, stop here and hand the failure up to whoever called me."In this page:
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
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),
}
}
Login to try C/C++/Java/PHP code in the editor
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
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"));
}
Login to try C/C++/Java/PHP code in the editor
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
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"));
}
Login to try C/C++/Java/PHP code in the editor
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
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(""));
}
Login to try C/C++/Java/PHP code in the editor
- Using
?inside a function whose return type is notResult(orOption), which fails to compile. - Forgetting
?only propagates the error -- it does not itself print anything or crash the program. - Mixing incompatible error types across multiple
?calls without a conversion, which the compiler will reject unless the types unify.
?after aResult-returning expression unwrapsOkvalues or returns early with theErr.- The enclosing function must itself return a compatible
Result(orOption) type for?to be used. ?dramatically reduces boilerplate compared to manually matching every fallible call.?can also be used withOption, returningNoneearly if the value isNone.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: