areller
areller

Reputation: 5238

Reverse generic constraint with Borrow trait

I'm new to rust and I've just learned about the Borrow trait.
From what I understand, the Borrow trait exposes a function borrow which works just like borrowing (i.e. &), but you can also use it in generic constraints (which you can't do with the normal borrowing syntax).

I have this function

pub fn get<Q>(&self, key: &Q) -> Option<&V>
    where K: Borrow<Q>,
          Q: Hash + Eq + ?Sized
{
    let bucket = self.bucket_key(key);
    self.buckets[bucket].iter().find(|&(ref ekey, _)| ekey.borrow() == key).map(|&(_, ref v)| v)
}

(I watched Jon Gjengset's video on YouTube)

And what is weird for me is that we constrain the K type, which is defined on the struct, to act like a Borrow<Q>.

So I was wondering what exactly this constraint says about K and Q.
Does it mean that we're constraining K to behave like a Borrow<Q>, or is K fixed here (since it was already defined on the struct) and we're constraining Q (and behind the scenes Rust converts it into something like Q: Unborrow<K> or something along these lines).

I hope that I make sense. I usually do C#, where something like that doesn't make sense.

Upvotes: 1

Views: 552

Answers (1)

edwardw
edwardw

Reputation: 13952

I assume you are referring to HashMap::get.

Don't overthink it. Rust trait system is basically a kind of logic, trait bounds are like logical constraints; here the type signature says:

  • Q has to be Hash, Eq and ?Sized
  • K has to be able to be borrowed as Q

In practice, it is for convenience:

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert(String::from("a"), 1u32);
    map.insert(String::from("b"), 2);

    assert_eq!(map.get("a"), Some(&1));
}

The map variable here is of type HashMap<String, u32>. If it weren't for the Borrow, you'll have to write:

map.get(&String::from("a"))

but since String can be borrowed as str and "a" is of type &'static str, you can write:

map.get("a")

The trait Borrow documentation has more elaborated explanation.

Upvotes: 2

Related Questions