I've got the following code:
use std::collections::HashMap;
fn main() {
let xs: Vec<&str> = vec!("a", "b", "c", "d");
let ys: Vec<i32> = vec!(1, 2, 3, 4);
let mut map: HashMap<String,i32> = HashMap::new();
for (x,y) in xs.iter().zip(ys) {
map.insert(x.to_owned(), y);
}
println!("{:?}", map);
}
Which results in error:
<anon>:8:20: 8:32 error: mismatched types:
expected `collections::string::String`,
found `&str`
(expected struct `collections::string::String`,
found &-ptr) [E0308]
<anon>:8 map.insert(x.to_owned(), y);
But it doesn't make sense to me. x should be &&str at this point. So why doesn't &&str.to_owned() automagically Deref the same way x.to_string() does at this point? (Why is x.to_owned() a &str?)
I know I can fix this by either using x.to_string(), or xs.into_iter() instead.
Because ToOwned is implemented for T where T: Clone, and Clone is implemented for &T. You need to roughly understand how pattern matching on &self works when both T and &T are available. Using a pseudo-syntax for exposition,
str → Stringstr doesn't match &self
&str (auto-ref) matches &self with self == str
Thus ToOwned<str> kicks in.
&str → String&str matches &self with self == str
Thus ToOwned<str> kicks in.
&&str → &str&&str matches &self with self == &str
Thus ToOwned<&T> kicks in.
Note that in this case, auto-deref can never kick in, since &T will always match in cases where T might, which lowers the complexity a bit. Note also that auto-ref only kicks in once (and once more for each auto-deref'd type).
To copy from huon's much better answer than mine,
The core of the algorithm is:
- For each each "dereference step"
U(that is, setU = Tand thenU = *T, ...)
- if there's a method
barwhere the receiver type (the type ofselfin the method) matchesUexactly , use it (a "by value method")- otherwise, add one auto-ref (take
&or&mutof the receiver), and, if some method's receiver matches&U, use it (an "autorefd method")
FWIW, .into() is normally prettier than .to_owned() (especially when types are implied; oft even when not), so I suggest that here. You still need a manual dereference, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With