Why is a trait bound present in the where clause but not in the function signature?

Viewed 135

I'm reading HashMap's get function, but I can't find the type parameter K in the source code.

Why does the K trait bound exist in the where clause, but not in the function signature?

pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
    where K: Borrow<Q>,
          Q: Hash + Eq
{
    self.search(k).map(|bucket| bucket.into_refs().1)
}
2 Answers

K is a type parameter of HashMap<K, V, S> and it's introduced at the beginning of the applicable impl block:

impl<K, V, S> HashMap<K, V, S>
    where K: Eq + Hash,
          S: BuildHasher

It is applicable for the whole block, including get, which adds an additional constraint, K: Borrow<Q>.

This way of specifying the type of get's k might be a bit awkward, but it enables us to e.g. do the following:

let mut map: HashMap<String, usize> = HashMap::new();

map.insert("herp".to_string(), 1);
map.insert("derp".to_string(), 2);

assert_eq!(map.get("herp"), Some(&1)); // we can search by &'static str (not only by a String)

I think the search method in get method body use K: Borrow<Q> trait bounds so the get method needs the same trait bounds.
And about using &str or &String for key values in get method parameters,
It's enough to use only &Q type

Related