Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The ? (question mark) operator is a unary postfix control-flow operator used for implicit error propagation and early returns. It evaluates an expression, unwraps and yields its inner value upon success, or immediately short-circuits the enclosing function by returning the failure state. It serves as syntactic sugar for a match expression combined with an early return.

Syntax

expression?

Mechanics on Result<T, E>

When applied to a Result<T, E>, the ? operator inspects the variant:
  1. If the variant is Ok(T), it extracts T and assigns it to the binding or passes it to the next expression.
  2. If the variant is Err(E), it immediately returns from the current function, yielding the error.
Crucially, when returning an Err, the ? operator implicitly invokes std::convert::From::from. This automatically converts the error type of the evaluated expression into the error type specified in the enclosing function’s return signature, provided the appropriate From trait is implemented. Desugared Equivalent:
// Using the ? operator
let val = expr?;

// Conceptual desugaring
let val = match expr {
    Ok(v) => v,
    Err(e) => return Err(std::convert::From::from(e)),
};

Mechanics on Option<T>

When applied to an Option<T>, the operator behaves similarly but without the type conversion step:
  1. If the variant is Some(T), it extracts and yields T.
  2. If the variant is None, it immediately returns None from the enclosing function.
Desugared Equivalent:
// Using the ? operator
let val = expr?;

// Conceptual desugaring
let val = match expr {
    Some(v) => v,
    None => return None,
};

The std::ops::Try Trait

Under the hood, the ? operator is not hardcoded to Result and Option. It operates on any type that implements the std::ops::Try and std::ops::FromResidual traits. Note: Custom implementation of the std::ops::Try and std::ops::FromResidual traits is currently unstable. Attempting to implement these traits for user-defined types on stable Rust will result in compiler errors; it requires a nightly compiler and the try_trait_v2 feature. The Try trait defines two associated types:
  • Output: The type yielded upon success (e.g., T).
  • Residual: The type yielded upon short-circuiting. For standard library types, these are Result<std::convert::Infallible, E> and Option<std::convert::Infallible>, representing the residual state without the success value.
When ? is invoked, it calls Try::branch. If it returns ControlFlow::Continue, execution proceeds with the unwrapped value. If it returns ControlFlow::Break, it passes the residual to FromResidual::from_residual to construct the enclosing function’s return value, and triggers the early return.

Function Signature Constraints

Because the ? operator forces an early return, the return type of the enclosing function must be compatible with the residual type of the expression being evaluated.
  • You cannot use ? on a Result inside a function that returns () or Option.
  • You cannot use ? on an Option inside a function that returns Result.
The enclosing function must return a type implementing FromResidual for the specific residual produced by the expression.
Master Rust with Deep Grasping Methodology!Learn More