# Module std::result

1.0.0 · source ·
Expand description

Error handling with the `Result` type.

`Result<T, E>` is the type used for returning and propagating errors. It is an enum with the variants, `Ok(T)`, representing success and containing a value, and `Err(E)`, representing error and containing an error value.

    enum Result<T, E> {
       Ok(T),
       Err(E),
    }

Run

Functions return `Result` whenever errors are expected and recoverable. In the `std` crate, `Result` is most prominently used for I/O.

A simple function returning `Result` might be defined and used like so:

    #[derive(Debug)]
    enum Version { Version1, Version2 }

    fn parse_version(header: &[u8]) -> Result<Version, &'static str> {
        match header.get(0) {
            None => Err("invalid header length"),
            Some(&1) => Ok(Version::Version1),
            Some(&2) => Ok(Version::Version2),
            Some(_) => Err("invalid version"),
        }
    }

    let version = parse_version(&[1, 2, 3, 4]);
    match version {
        Ok(v) => println!("working with version: {v:?}"),
        Err(e) => println!("error parsing header: {e:?}"),
    }

Run

Pattern matching on `Result`s is clear and straightforward for simple cases, but `Result` comes with some convenience methods that make working with it more succinct.

    let good_result: Result<i32, i32> = Ok(10);
    let bad_result: Result<i32, i32> = Err(10);

    // The `is_ok` and `is_err` methods do what they say.
    assert!(good_result.is_ok() && !good_result.is_err());
    assert!(bad_result.is_err() && !bad_result.is_ok());

    // `map` consumes the `Result` and produces another.
    let good_result: Result<i32, i32> = good_result.map(|i| i + 1);
    let bad_result: Result<i32, i32> = bad_result.map(|i| i - 1);

    // Use `and_then` to continue the computation.
    let good_result: Result<bool, i32> = good_result.and_then(|i| Ok(i == 11));

    // Use `or_else` to handle the error.
    let bad_result: Result<i32, i32> = bad_result.or_else(|i| Ok(i + 20));

    // Consume the result and return the contents with `unwrap`.
    let final_awesome_result = good_result.unwrap();

Run

## Results must be used

A common problem with using return values to indicate errors is that it is easy to ignore the return value, thus failing to handle the error. `Result` is annotated with the `#[must_use]` attribute, which will cause the compiler to issue a warning when a Result value is ignored. This makes `Result` especially useful with functions that may encounter errors but don’t otherwise return a useful value.

Consider the `write_all` method defined for I/O types by the `Write` trait:

    use std::io;

    trait Write {
        fn write_all(&mut self, bytes: &[u8]) -> Result<(), io::Error>;
    }

Run

Note: The actual definition of `Write` uses `io::Result`, which is just a synonym for `Result<T, io::Error>`.

This method doesn’t produce a value, but the write may fail. It’s crucial to handle the error case, and not write something like this:

    use std::fs::File;
    use std::io::prelude::*;

    let mut file = File::create("valuable_data.txt").unwrap();
    // If `write_all` errors, then we'll never know, because the return
    // value is ignored.
    file.write_all(b"important message");

Run

If you do write that in Rust, the compiler will give you a warning (by default, controlled by the `unused_must_use` lint).

You might instead, if you don’t want to handle the error, simply assert success with `expect`. This will panic if the write fails, providing a marginally useful message indicating why:

    use std::fs::File;
    use std::io::prelude::*;

    let mut file = File::create("valuable_data.txt").unwrap();
    file.write_all(b"important message").expect("failed to write message");

Run

You might also simply assert success:

    assert!(file.write_all(b"important message").is_ok());

Run

Or propagate the error up the call stack with `?`:

    fn write_message() -> io::Result<()> {
        let mut file = File::create("valuable_data.txt")?;
        file.write_all(b"important message")?;
        Ok(())
    }

Run

## The question mark operator, `?`

When writing code that calls many functions that return the `Result` type, the error handling can be tedious. The question mark operator, `?`, hides some of the boilerplate of propagating errors up the call stack.

It replaces this:

    use std::fs::File;
    use std::io::prelude::*;
    use std::io;

    struct Info {
        name: String,
        age: i32,
        rating: i32,
    }

    fn write_info(info: &Info) -> io::Result<()> {
        // Early return on error
        let mut file = match File::create("my_best_friends.txt") {
               Err(e) => return Err(e),
               Ok(f) => f,
        };
        if let Err(e) = file.write_all(format!("name: {}\n", info.name).as_bytes()) {
            return Err(e)
        }
        if let Err(e) = file.write_all(format!("age: {}\n", info.age).as_bytes()) {
            return Err(e)
        }
        if let Err(e) = file.write_all(format!("rating: {}\n", info.rating).as_bytes()) {
            return Err(e)
        }
        Ok(())
    }

Run

With this:

    use std::fs::File;
    use std::io::prelude::*;
    use std::io;

    struct Info {
        name: String,
        age: i32,
        rating: i32,
    }

    fn write_info(info: &Info) -> io::Result<()> {
        let mut file = File::create("my_best_friends.txt")?;
        // Early return on error
        file.write_all(format!("name: {}\n", info.name).as_bytes())?;
        file.write_all(format!("age: {}\n", info.age).as_bytes())?;
        file.write_all(format!("rating: {}\n", info.rating).as_bytes())?;
        Ok(())
    }

Run

It’s much nicer!

Ending the expression with `?` will result in the `Ok`’s unwrapped value, unless the result is `Err`, in which case `Err` is returned early from the enclosing function.

`?` can be used in functions that return `Result` because of the early return of `Err` that it provides.

## Method overview

In addition to working with pattern matching, `Result` provides a wide variety of different methods.

### Querying the variant

The `is_ok` and `is_err` methods return `true` if the `Result` is `Ok` or `Err`, respectively.

### Adapters for working with references

- `as_ref` converts from `&Result<T, E>` to `Result<&T, &E>`
- `as_mut` converts from `&mut Result<T, E>` to `Result<&mut T, &mut E>`
- `as_deref` converts from `&Result<T, E>` to `Result<&T::Target, &E>`
- `as_deref_mut` converts from `&mut Result<T, E>` to `Result<&mut T::Target, &mut E>`

### Extracting contained values

These methods extract the contained value in a `Result<T, E>` when it is the `Ok` variant. If the `Result` is `Err`:

- `expect` panics with a provided custom message
- `unwrap` panics with a generic message
- `unwrap_or` returns the provided default value
- `unwrap_or_default` returns the default value of the type `T` (which must implement the `Default` trait)
- `unwrap_or_else` returns the result of evaluating the provided function

The panicking methods `expect` and `unwrap` require `E` to implement the `Debug` trait.

These methods extract the contained value in a `Result<T, E>` when it is the `Err` variant. They require `T` to implement the `Debug` trait. If the `Result` is `Ok`:

- `expect_err` panics with a provided custom message
- `unwrap_err` panics with a generic message

### Transforming contained values

These methods transform `Result` to `Option`:

- `err` transforms `Result<T, E>` into `Option<E>`, mapping `Err(e)` to `Some(e)` and `Ok(v)` to `None`
- `ok` transforms `Result<T, E>` into `Option<T>`, mapping `Ok(v)` to `Some(v)` and `Err(e)` to `None`
- `transpose` transposes a `Result` of an `Option` into an `Option` of a `Result`

This method transforms the contained value of the `Ok` variant:

- `map` transforms `Result<T, E>` into `Result<U, E>` by applying the provided function to the contained value of `Ok` and leaving `Err` values unchanged

This method transforms the contained value of the `Err` variant:

- `map_err` transforms `Result<T, E>` into `Result<T, F>` by applying the provided function to the contained value of `Err` and leaving `Ok` values unchanged

These methods transform a `Result<T, E>` into a value of a possibly different type `U`:

- `map_or` applies the provided function to the contained value of `Ok`, or returns the provided default value if the `Result` is `Err`
- `map_or_else` applies the provided function to the contained value of `Ok`, or applies the provided default fallback function to the contained value of `Err`

### Boolean operators

These methods treat the `Result` as a boolean value, where `Ok` acts like `true` and `Err` acts like `false`. There are two categories of these methods: ones that take a `Result` as input, and ones that take a function as input (to be lazily evaluated).

The `and` and `or` methods take another `Result` as input, and produce a `Result` as output. The `and` method can produce a `Result<U, E>` value having a different inner type `U` than `Result<T, E>`. The `or` method can produce a `Result<T, F>` value having a different error type `F` than `Result<T, E>`.

method | self | input | output
--- | --- | --- | ---
`and` | `Err(e)` | (ignored) | `Err(e)`
`and` | `Ok(x)` | `Err(d)` | `Err(d)`
`and` | `Ok(x)` | `Ok(y)` | `Ok(y)`
`or` | `Err(e)` | `Err(d)` | `Err(d)`
`or` | `Err(e)` | `Ok(y)` | `Ok(y)`
`or` | `Ok(x)` | (ignored) | `Ok(x)`

The `and_then` and `or_else` methods take a function as input, and only evaluate the function when they need to produce a new value. The `and_then` method can produce a `Result<U, E>` value having a different inner type `U` than `Result<T, E>`. The `or_else` method can produce a `Result<T, F>` value having a different error type `F` than `Result<T, E>`.

method | self | function input | function result | output
--- | --- | --- | --- | ---
`and_then` | `Err(e)` | (not provided) | (not evaluated) | `Err(e)`
`and_then` | `Ok(x)` | `x` | `Err(d)` | `Err(d)`
`and_then` | `Ok(x)` | `x` | `Ok(y)` | `Ok(y)`
`or_else` | `Err(e)` | `e` | `Err(d)` | `Err(d)`
`or_else` | `Err(e)` | `e` | `Ok(y)` | `Ok(y)`
`or_else` | `Ok(x)` | (not provided) | (not evaluated) | `Ok(x)`

### Comparison operators

If `T` and `E` both implement `PartialOrd` then `Result<T, E>` will derive its `PartialOrd` implementation. With this order, an `Ok` compares as less than any `Err`, while two `Ok` or two `Err` compare as their contained values would in `T` or `E` respectively. If `T` and `E` both also implement `Ord`, then so does `Result<T, E>`.

    assert!(Ok(1) < Err(0));
    let x: Result<i32, ()> = Ok(0);
    let y = Ok(1);
    assert!(x < y);
    let x: Result<(), i32> = Err(0);
    let y = Err(1);
    assert!(x < y);

Run

### Iterating over `Result`

A `Result` can be iterated over. This can be helpful if you need an iterator that is conditionally empty. The iterator will either produce a single value (when the `Result` is `Ok`), or produce no values (when the `Result` is `Err`). For example, `into_iter` acts like `once(v)` if the `Result` is `Ok(v)`, and like `empty()` if the `Result` is `Err`.

Iterators over `Result<T, E>` come in three types:

- `into_iter` consumes the `Result` and produces the contained value
- `iter` produces an immutable reference of type `&T` to the contained value
- `iter_mut` produces a mutable reference of type `&mut T` to the contained value

See Iterating over `Option` for examples of how this can be useful.

You might want to use an iterator chain to do multiple instances of an operation that can fail, but would like to ignore failures while continuing to process the successful results. In this example, we take advantage of the iterable nature of `Result` to select only the `Ok` values using `flatten`.

    let mut results = vec![];
    let mut errs = vec![];
    let nums: Vec<_> = ["17", "not a number", "99", "-27", "768"]
       .into_iter()
       .map(u8::from_str)
       // Save clones of the raw `Result` values to inspect
       .inspect(|x| results.push(x.clone()))
       // Challenge: explain how this captures only the `Err` values
       .inspect(|x| errs.extend(x.clone().err()))
       .flatten()
       .collect();
    assert_eq!(errs.len(), 3);
    assert_eq!(nums, [17, 99]);
    println!("results {results:?}");
    println!("errs {errs:?}");
    println!("nums {nums:?}");

Run

### Collecting into `Result`

`Result` implements the `FromIterator` trait, which allows an iterator over `Result` values to be collected into a `Result` of a collection of each contained value of the original `Result` values, or `Err` if any of the elements was `Err`.

    let v = [Ok(2), Ok(4), Err("err!"), Ok(8)];
    let res: Result<Vec<_>, &str> = v.into_iter().collect();
    assert_eq!(res, Err("err!"));
    let v = [Ok(2), Ok(4), Ok(8)];
    let res: Result<Vec<_>, &str> = v.into_iter().collect();
    assert_eq!(res, Ok(vec![2, 4, 8]));

Run

`Result` also implements the `Product` and `Sum` traits, allowing an iterator over `Result` values to provide the `product` and `sum` methods.

    let v = [Err("error!"), Ok(1), Ok(2), Ok(3), Err("foo")];
    let res: Result<i32, &str> = v.into_iter().sum();
    assert_eq!(res, Err("error!"));
    let v = [Ok(1), Ok(2), Ok(21)];
    let res: Result<i32, &str> = v.into_iter().product();
    assert_eq!(res, Ok(42));

Run

## Structs

- IntoIter
  An iterator over the value in a `Ok` variant of a `Result`.
- Iter
  An iterator over a reference to the `Ok` variant of a `Result`.
- IterMut
  An iterator over a mutable reference to the `Ok` variant of a `Result`.

## Enums

- Result
  `Result` is a type that represents either success (`Ok`) or failure (`Err`).