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 Result<T, E> type in Rust is a generic enumeration used for returning and propagating the outcome of operations that can fail. It represents either a successful execution containing a value of type T, or a failed execution containing an error of type E.
#[must_use]
pub enum Result<T, E> {
    Ok(T),
    Err(E),
}

Core Characteristics

  • Generics (T, E): T binds to the success value’s type, and E binds to the error value’s type. These types are entirely independent.
  • Prelude Inclusion: The Result enum and its variants (Ok and Err) are included in the Rust prelude. They are globally available without explicit use statements.
  • #[must_use] Attribute: The Rust compiler enforces error handling by emitting a warning if a function returns a Result and the caller ignores it.

Value Extraction via Pattern Matching

The fundamental mechanism for interacting with a Result is exhaustive pattern matching using the match control flow operator. This forces the developer to explicitly handle both the Ok and Err states.
fn check_positive(number: i32) -> Result<i32, String> {
    if number > 0 {
        Ok(number)
    } else {
        Err(String::from("Number is not positive"))
    }
}

fn main() {
    let outcome: Result<i32, String> = check_positive(5);

    match outcome {
        Ok(success_value) => println!("Success: {}", success_value),
        Err(error_value)  => println!("Error: {}", error_value),
    }
}

The Try Operator (?)

The ? operator provides syntactic sugar for early error propagation. When appended to an expression evaluating to a Result, it unwraps the Ok value or immediately returns the Err from the enclosing function. Critical Constraint: The ? operator can only be used inside functions whose return type implements the std::ops::Try trait, such as Result or Option. Beginners frequently encounter compiler errors by attempting to use ? inside a standard main function that returns (). To use ? in main, the function signature must be modified to return a compatible type like Result<(), E>.
use std::num::ParseIntError;

fn parse_and_double(input: &str) -> Result<i32, ParseIntError> {
    // The `?` operator unwraps the i32 or returns ParseIntError early
    let value = input.parse::<i32>()?;
    Ok(value * 2)
}

fn main() -> Result<(), ParseIntError> {
    let result = parse_and_double("10")?;
    println!("Result: {}", result);
    Ok(())
}
Under the hood, the ? operator desugars into a match expression that invokes the From trait, allowing for automatic type conversion of the error (E) into the enclosing function’s expected error type.
use std::num::ParseIntError;

// Desugared equivalent of the `?` operator in the previous example
fn parse_and_double_desugared(input: &str) -> Result<i32, ParseIntError> {
    let value = match input.parse::<i32>() {
        Ok(val) => val,
        Err(err) => return Err(From::from(err)),
    };
    Ok(value * 2)
}

Collection via FromIterator

Result implements the FromIterator trait, enabling an Iterator over Result<T, E> values to be collected directly into a single Result<Collection<T>, E> (such as Result<Vec<T>, E>). During iteration, if an Err is encountered, the collection process short-circuits and returns that first Err. If all elements are Ok, it returns an Ok containing the populated collection.
use std::num::ParseIntError;

fn main() {
    let strings = vec!["10", "20", "30"];
    
    // Collects Iterator<Item = Result<i32, ParseIntError>> into Result<Vec<i32>, ParseIntError>
    let numbers: Result<Vec<i32>, ParseIntError> = strings
        .into_iter()
        .map(|s| s.parse::<i32>())
        .collect();

    assert_eq!(numbers, Ok(vec![10, 20, 30]));
}

Standard Library Combinators

The Result API provides functional-style combinators to transform, chain, or extract values without explicit match blocks.

Interoperability with Option

  • ok(self) -> Option<T>: Converts Result<T, E> into Option<T>, consuming self and discarding the error value.
  • err(self) -> Option<E>: Converts Result<T, E> into Option<E>, consuming self and discarding the success value.

State Interrogation

  • is_ok(&self) -> bool: Returns true if the result is Ok.
  • is_err(&self) -> bool: Returns true if the result is Err.

Transformation

  • map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E>: Applies a function to the Ok value, leaving an Err value untouched.
  • map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F>: Applies a function to the Err value, leaving an Ok value untouched.

Chaining (Monadic Operations)

  • and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E>: Calls op if the result is Ok, otherwise returns the Err value of self. Used for chaining multiple operations that return Result.
  • or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F>: Calls op if the result is Err, otherwise returns the Ok value of self.

Extraction (Panicking)

  • unwrap(self) -> T: Returns the contained Ok value. Panics if the value is an Err.
  • expect(self, msg: &str) -> T: Returns the contained Ok value. Panics with the provided custom message if the value is an Err.

Extraction (Safe Fallbacks)

  • unwrap_or(self, default: T) -> T: Returns the contained Ok value or a provided default T.
  • unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T: Returns the contained Ok value or computes a default T from a closure.
Master Rust with Deep Grasping Methodology!Learn More