Motivation
Override default Eq impl for specific type when using HashMap.
Suppose we have struct Foo: Eq + Hash
whose default Eq impl is undesirable. Foo
is expensive and not Copy
-able.
Path to the problem
Newtype pattern
We define a wrapper type struct Wrapper<Foo>(Foo): Eq + Hash
and use HashMap<Wrapper<Foo>, Bar>
Wrapping HashMap::remove
Now we wish to provide a wrapped version of the HashMap::remove
and have the following signature, to allow us just to use this new HashMap like before.
fn wrapped_remove(hash_map: &HashMap<Wrapper<Foo>, Bar>, foo: &Foo) -> Option<Bar> {
hash_map.remove(todo!("We dont have a &Wrapper(*foo)"))
}
Instantly we found the type incompatibility.
Type converting for HashMap::remove
According to HashMap's signature, we just need to have a type Q which
Wrapper<Foo>: Borrow<Q>
Q: Eq + Hash
-
Q
can be constructed from&Foo
Suppose we have a second generic type to serve as Q
. Let's call it struct WrappedRef<'a, Foo>(&'a Foo) : Eq + Hash
Then we need to have
impl Borrow<WrappedRef<'a, Foo>> for Wrapper<Foo> {
fn borrow<'b>(&'b self) -> &'b WrappedRef<'a, Foo> {
todo!("Lifetime error and temporary reference cannot be returned error")
}
}
Instantly we found the lifetime problem. We can't add the lifetime bound anywhere in the impl otherwise it breaks Borrow
's signature.
Question
- Is there a way to implement this
wrapped_remove
interface as is, in order to hide this layer of newtype abstraction? - Is there other way to override Eq impls for HashMaps, other than the newtype pattern?