Confusing error while calling contains_key on HashMap<&str, _>

I have this little program.

use std::collections::HashMap;
fn main() {
    let mut map: HashMap<&str, u32> = HashMap::new();
    let new = "TOMATO".to_string();
    if !map.contains_key(&new) {}
}

When I try to compile this program, I get an error that I believe is quite confusing.

error[E0277]: the trait bound `&str: std::borrow::Borrow<std::string::String>` is not satisfied
 --> src/main.rs:5:13
  |
5 |     if !map.contains_key(&new) {}
  |             ^^^^^^^^^^^^ the trait `std::borrow::Borrow<std::string::String>` is not implemented for `&str`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

I have already resolved this and there were two ways to resolve this.

  1. Use HashMap<String, _> signature instead of HashMap<&str, _>
  2. Replace, if !map.contains_key(&new) {} with if !map.contains_key(new.as_str()) {}.

I am wondering if anyone else also found the compiler error to be confusing and maybe if we can do anything to improve it? Playground link

After looking up what Borrow actually means from the docs, I was able to translate this to:

&str cannot be borrowed as a String

Which makes perfect sense; the relationship goes the other way around. To lookup a key in a HashMap, you to provide a reference that matches its owned key type.

For me, the most confisung part of the error message is the ambiguity in the trait name Borrow: It isn’t immediately clear what A: Borrow<B> means— Is A the reference type of B, or is B the reference type of A?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.