What is the proper way to index into a HashMap<&String, V>
with a &str
? Rust reports that &String
is not Borrow<str>
, which is required for indexing. (This seems a bit silly to me; if T: Borrow<U>
then surely &T: Borrow<U>
should also hold?)
use std::collections::HashMap;
fn main() {
let strings = vec!["x".to_owned(), "y".to_owned(), "z".to_owned()];
let m = [0, 1, 2]
.into_iter()
.map(|i| (&strings[i], i))
.collect::<HashMap<&String, usize>>();
let zero = m["x"];
}
error[E0277]: the trait bound `&String: Borrow<str>` is not satisfied
--> src/main.rs:9:18
|
9 | let zero = m["x"];
| ^^^ the trait `Borrow<str>` is not implemented for `&String`, which is required by `HashMap<&String, usize>: Index<&_>`
|
= help: the trait `Borrow<str>` is implemented for `String`
= help: for that trait implementation, expected `String`, found `&String`
= note: required for `HashMap<&String, usize>` to implement `Index<&str>`
Obviously, because I constructed this particular HashMap, I could go back and change its key type to &str
instead. But supposing I’m handed a HashMap<&String, V>
, what is the proper way to index it? Constructing a whole String
just to take a reference to it seems wasteful.
3
impl<U, T: Borrow<U>> Borrow<U> for &T {}
conflicts with the existing
impl<T> Borrow<T> for T {
// …
}
so it can’t be added.
Playground
Why do you use &String
as keys to begin with? The preferred way would be to use &str
which can trivially be created from a &String
and you don’t have the problem and is more general. When you’re not in control creating a String
just to index is your only option.