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 → String
str
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 = T
and thenU = *T
, ...)
- if there's a method
bar
where the receiver type (the type ofself
in the method) matchesU
exactly , use it (a "by value method")- otherwise, add one auto-ref (take
&
or&mut
of 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