Reputation: 3573
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:
&str
coerce with &String
?contains
work without the extra allocation?Upvotes: 13
Views: 3266
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
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());
Not the "real" answer anymore, but I let this here for people who might be interested in a solution for this.
Upvotes: 11
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