How do I use the Option::ok_or() method correctly?

Viewed 3054

I'm trying to understand how to use the question mark operator for error handling in Rust. I have this code:

fn main() -> Result<(), &'static str> {
    let foo: i32 = Some("1")
        .ok_or(Err("error 1"))?
        .parse()
        .or(Err("error 2"))?;
    Ok(())
}

This code can not be compiled for some reason:

error[E0277]: the trait bound `&str: std::convert::From<std::result::Result<_, &str>>` is not satisfied
 --> src/main.rs:2:20
  |
2 |       let foo: i32 = Some("1")
  |  ____________________^
3 | |         .ok_or(Err("error 1"))?
  | |_______________________________^ the trait `std::convert::From<std::result::Result<_, &str>>` is not implemented for `&str`
  |
  = note: required by `std::convert::From::from`

The Rust book has an example usage of the question mark operator:

use std::io;
use std::io::Read;
use std::fs::File;

fn read_username_from_file() -> Result<String, io::Error> {
    let mut s = String::new();

    File::open("hello.txt")?.read_to_string(&mut s)?;

    Ok(s)
}

In my opinion, it doesn't differ much from my example in sense of handling errors. I cannot see a reason for my code to be invalid. If the From trait should be implemented for all kinds of Result why does the code from the Rust book work fine?

1 Answers

Unlike or, ok_or takes an E, not a full Result<T, E> (because it wouldn't have anything to do if passed an Ok). Just pass the error string directly:

fn main() -> Result<(), &'static str> {
   let foo: i32 = Some("1")
       .ok_or("error 1")?
       .parse()
       .or(Err("error 2"))?;
    Ok(())
}

The reason the error message mentions the From trait is because ? implicitly uses From to convert the expression's error type into the return value's error type. If it worked, .ok_or(Err("error 1")) would return a value of Result<&'static str, Result<_, &'static str>> (_ could be almost anything, since Err doesn't specify). The ? operator attempts to find an implementation of From that would convert Result<_, &'static str> (the expression's error type) into &'static str (the return value's error type). Since no such From implementation exists, the compiler emits an error.

Related