Question Mark Operator in Rust

Nilesh Katuwal Jan 30, 2023
  1. the Question Mark Operator (?) in Rust
  2. Error Propagation in Rust
  3. When and Where to Use the Question Mark (?) Operator in Rust
Question Mark Operator in Rust

This tutorial is about Rust’s question mark operator (?).

the Question Mark Operator (?) in Rust

The question mark operator (?) unwraps fair values and returns erroneous values to the calling function, which is then passed on to the caller. A unary postfix operator can only be applied to the types Result<T, E> and Option<T> and cannot be used to any other types.

Things can become cluttered when using the match operator to chain results together; fortunately, the ? operator can make things a little more orderly. ? is used at the end of an expression that returns a Result.

It is equivalent to a match expression in which the Err(err) branch expands to an early return Err(From::from(err)), and the Ok(ok) branch expands to an ok expression, and the Err(err) branch expands to an early return Err(From::from(err)) branch.

? cannot be overloaded.

As you may have seen, Rust is a rule-following language. Therefore, although it contains panics, their use for error handling is discouraged as they are meant for unrecoverable errors.

Additionally, we must study error propagation to understand how to use the ? mark directly.

Error Propagation in Rust

Error propagation is the process of propagating or spreading up, or returning error information found in code that is often invoked by a caller function to enable the caller function to handle the problem effectively.

Example:

fn main() {
    let result = char_in_second_word(&"Learning when question mark used", &'i');

    println!("The value is {}", result.unwrap_or(1))
}


fn char_in_second_word(sentence: &str, char: &char) -> Option<usize> {
    let second_word =  match sentence.split(" ").next().is_some() == true {
        true => sentence.split(" ").next().unwrap(),
        false => return None
    };

    second_word.find(|x| &x == char)
}

Output:

The value is 5

Take note of the simple utility function char_in_second_word, which returns the index of the character discovered in the first word detected on a literal string.

However, if the string literal is Learning and the character we’re looking for is I, the returned index value will be Some(5) because the string literal’s first word is Learning, which contains the letter I in position 5 of the array of characters.

But using a question mark, the codes can be made easier and simpler.

In Rust, Result is used for error handling. The ? operator can be used only in a function that returns Result or Option.

Example:

use std::num::ParseIntError;

fn main() -> Result<(), ParseIntError>
{
    let num = "7".parse::<i32>()?;
    println!("{:?}", num);
    Ok(())
}

Output:

7

The ? operator could be used on a Result type if the function contained also returns a Result.

Each time you see a ?, it indicates the possibility of an early return from the function in which the ? is utilized.

When and Where to Use the Question Mark (?) Operator in Rust

There are some circumstances where utilization of the question mark ? operator cannot be made. For example, the description states that the ? operator is only used in functions that return the types Result or Option.

This does not exclude working with the Result and Option types within a function. The ? operator, on the other hand, should be used strictly with types that return the same type in a function.

In other words, if the function returns a type named Result, utilize the ? operator in a type named Result. If the function returns an Option, the ? operator should be used in an Option type.

Attempting to use the ? operator on both Result and Option types in a function that returns only one of the two kinds will result in an error. For illustration, consider the following code.

fn err_fxn() -> Result<i32, String> {
    let x = Ok("The go!")?;
    let y = Some(1)?;

    Ok(x)
}

Running the above source code will cause the error as stated below.

the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`

We should remember that, in error propagation, the ? is used as a shortcut.

If the ? character is used in a type other than the one returned by a function, there is a possibility of propagating mistakes unrelated to the type defined on the function to return.

Fortunately, Rust is intelligent enough to catch these problems during the compilation process. As a result, such mistakes would not arise during code execution.