Edd Barrett
Edd Barrett

Reputation: 3573

Why does a &str not coerce to a &String when using Vec::contains?

A friend asked me to explain the following quirk in Rust. I was unable to, hence this question:

fn main() {
    let l: Vec<String> = Vec::new();
    //let ret = l.contains(&String::from(func())); // works
    let ret = l.contains(func());  // does not work
    println!("ret: {}", ret);
}

fn func() -> & 'static str {
    "hello"
}

Example on the Rust Playground

The compiler will complain like this:

error[E0308]: mismatched types
 --> src/main.rs:4:26
  |
4 |     let ret = l.contains(func());  // does not work
  |                          ^^^^^^ expected struct `std::string::String`, found str
  |
  = note: expected type `&std::string::String`
             found type `&'static str`

In other words, &str does not coerce with &String.

At first I thought it was to do with 'static, however that is a red herring.

The commented line fixes the example at the cost of an extra allocation.

My questions:

Upvotes: 13

Views: 3266

Answers (3)

Edd Barrett
Edd Barrett

Reputation: 3573

It seems that the Rust developers intend to adjust the signature of contains to allow the example posted above to work.

In some sense, this is a known bug in contains. It sounds like the fix won't allow those types to coerce, but will allow the above example to work.

Upvotes: 8

hellow
hellow

Reputation: 13430

Your first question should be answer already by @Marko.

Your second question, should be easy to answer as well, just use a closure:

let ret = l.iter().any(|x| x == func());

Edit:

Not the "real" answer anymore, but I let this here for people who might be interested in a solution for this.

Upvotes: 11

Marko Popovic
Marko Popovic

Reputation: 4153

std::string::String is a growable, heap-allocated data structure whereas string slice (str) is an immutable fixed-length string somewhere in memory. String slice is used as a borrowed type, via &str. Consider it as view to some string date that resides somewhere in memory. That is why it does not make sense for str to coerce to String, while the other way around perfectly makes sense. You have a heap-allocated String somewhere in memory and you want to use a view (a string slice) to that string.

To answer your second question. There is no way to make the code work in the current form. You either need to change to a vector of string slices (that way, there will be no extra allocation) or use something other then contains method.

Upvotes: 3

Related Questions