Here’s a prototype of an extension of what HashMap::get is using Borrow for.
What Problem does it Solve?
You have a hash table with key type (String, String) and you want to do a table lookup without allocating strings. It allows lookup not using a custom type like Pair(&str, &str) (or even using the (&str, &str) tuple if libstd buys into it).
Implementation
Two things are needed: The substitute key (Q) must be hashable (like the K type), and there must be a K to Q equality function (a function to avoid the limitations of Borrow).
/// Key lookup trait.
///
/// This trait allows hash table lookup to be customized.
/// It has one blanket implementation that uses the regular `Borrow` solution,
/// just like `HashMap` and `BTreeMap` do, so that you can pass `&str` to lookup
/// into a map with `String` keys and so on.
///
/// # Contract
///
/// The implementor must hash like `K`.
pub trait Lookup<K: ?Sized> : Hash {
/// Compare self to `key` and return `true` if they are equal.
fn equal(&self, key: &K) -> bool;
}
impl<Q: ?Sized, K: ?Sized> Lookup<K> for Q
where Q: Eq + Hash,
K: Borrow<Q>,
{
fn equal(&self, key: &K) -> bool {
*self == *key.borrow()
}
}
Implementation in a custom hash map here: https://github.com/bluss/ordermap/pull/10/files (API for .get() was identical to std’s HashMap). The trait could also be called Equivalent.
Drawbacks
- Type inference regressions? (Don’t know)
- Ad hoc.