Search code examples
typesrustunwrap

How to unwrap_or to String


When using unwrap_or, how do I get a String?

I've distilled my problem down to this (with more type annotation than needed):

fn main() {
    let mut blah: String;
    let opt: Option<&str> = Some("foo");
    blah = opt.unwrap_or("bar");
}

This (reasonably) tells me that we need a String not a &str.

error[E0308]: mismatched types
  --> src/main.rs:33:12
   |
33 |     blah = opt.unwrap_or("bar");
   |            ^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found &str
   |
   = note: expected type `std::string::String`
   = note:    found type `&str`

So I try to provide the type wanted.

blah = opt.unwrap_or("bar".to_string());

But I get told off:

error[E0308]: mismatched types
  --> src/main.rs:33:26
   |
33 |     blah = opt.unwrap_or("bar".to_string());
   |                          ^^^^^^^^^^^^^^^^^ expected &str, found struct `std::string::String`
   |
   = note: expected type `&str`
   = note:    found type `std::string::String`

error[E0308]: mismatched types
  --> src/main.rs:33:12
   |
33 |     blah = opt.unwrap_or("bar".to_string());
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found &str
   |
   = note: expected type `std::string::String`
   = note:    found type `&str`

Solution

  • You misread the first error. The problem is not in the type passed to unwrap_or(), but in the type returned by unwrap_or(). Since you are assigning to a String, the right-hand-side of the assignment must also provide a String. The original error can be fixed simply by adding to_string() after the unwrap_or:

    let mut blah: String;
    let opt: Option<&str> = Some("foo");
    blah = opt.unwrap_or("bar").to_string();
    

    It is of course also possible for Option to contain a string, in which case your attempted fix would work just fine:

    let mut blah: String;
    let opt: Option<String> = Some("foo".to_string());
    blah = opt.unwrap_or("bar".to_string());
    

    Note that the type annotations are not required in either variable, Rust's type inference is smart enough to figure it out on its own.