CodeBlanks Logo Icon CodeBlanks

? operator

Propagate errors automatically to the caller with ?.

The ? operator

? unpacks a Result: if it's Ok(v) it gives v, if it's Err(e) it immediately returns Err(e) from the function. It reduces error-propagation code to one character:

use std::num::ParseIntError;

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

? can only be used in functions that return Result (or Option).

? and From

Before returning the error, ? converts it to the function's error type with From::from. This way different error types can be gathered into one type:

use std::error::Error;

fn oku(s: &str) -> Result<f64, Box<dyn Error>> {
    let n: i32 = s.parse()?;          // ParseIntError → Box<dyn Error>
    let k: f64 = "2.5".parse()?;      // ParseFloatError → Box<dyn Error>
    Ok(n as f64 * k)
}

In a function returning Option, ? propagates None upward.

Practice Add texts

Write the function fn topla(a: &str, b: &str) -> Result<i32, ParseIntError> above with ?. Print the results of topla("2", "3") and topla("2", "x") with {:?}, separated by a space.

Starter code

main.rs
use std::num::ParseIntError;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::num::ParseIntError;

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

fn main() {
    println!("{:?} {:?}", topla("2", "3"), topla("2", "x"));
}

Expected output

Ok(5) Err(ParseIntError { kind: InvalidDigit })

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Why doesn't <code>fn main() { let n: i32 = "5".parse()?; }</code> compile?

  • "5" is invalid
  • It compiles
  • main returns (); ? needs it to return a Result Correct answer
  • parse is misused

Explanation: main can return a Result too: fn main() -> Result<(), Box<dyn std::error::Error>> { ...; Ok(()) }.

2 Propagate the error

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

Explanation: ? returns the Err to the caller immediately on failure.

3 Syntax and meaning

Term Meaning
x? Unpack Ok, return on Err
Box<dyn Error> Any error type
From::from Error conversion
opt? Propagates None

All lessons in Beginner