8

I expect the same result for both of these code samples:

let maybe_string = Some(String::from("foo"));
let string = if let Some(ref value) = maybe_string { value } else { "none" };
let maybe_string = Some(String::from("foo"));
let string = maybe_string.as_ref().unwrap_or("none");

The second sample gives me an error:

error[E0308]: mismatched types
 --> src/main.rs:3:50
  |
3 |     let string = maybe_string.as_ref().unwrap_or("none");
  |                                                  ^^^^^^ expected struct `std::string::String`, found str
  |
  = note: expected type `&std::string::String`
             found type `&'static str`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
user3414682
  • 107
  • 1
  • 6

1 Answers1

11

Because that's how Option::as_ref is defined:

impl<T> Option<T> {
    fn as_ref(&self) -> Option<&T>
}

Since you have an Option<String>, then the resulting type must be Option<&String>.

Instead, you can add in String::as_str:

maybe_string.as_ref().map(String::as_str).unwrap_or("none");

Or the shorter:

maybe_string.as_ref().map_or("none", String::as_str);

As of Rust 1.40, you can also use Option::as_deref.

maybe_string.as_deref().unwrap_or("none");

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 2
    Related discussion on ways of going from `Option` to `Option<&str>` is occurring in [a proposed RFC](https://github.com/rust-lang/rfcs/pull/1792). – Shepmaster May 24 '17 at 16:24