I want to simplify defining custom comparison traits (PartialEq
, Eq
, PartialOrd
, Ord
, Hash
, etc.).
This is my idea:
- Define a trait
Key
that extracts a key for comparing. - Define a wrapper structure
Keyed
that wraps an object that implements theKey
trait. - Implement various comparison traits for the
Keyed
structure base on the extracted key. This indirection is to avoid the orphan rule that prevents me from defining comparison traits on types that defineKey
traits directly.
The Key
trait is defined as follows:
trait Key<'a> {
type Key;
fn key(&'a self) -> Self::Key;
}
This trait can handle both and borrowed keys and non-borrowed keys :
struct NonBorrowedKey<K, V> {
key: K,
value: V,
}
impl<'a, K: Copy, V> Key<'a> for NonBorrowedKey<K, V> {
type Key = K;
fn key(&'a self) -> Self::Key {
self.key
}
}
struct BorrowedKey<K, V> {
key: K,
value: V,
}
impl<'a, K: 'a, V> Key<'a> for BorrowedKey<K, V> {
type Key = &'a K;
fn key(&'a self) -> Self::Key {
&self.key
}
}
The Keyed
structured is:
struct Keyed<T>(pub T);
Now I can implement various traits for the Keyed
structure. For example, PartialEq
:
impl<T> PartialEq for Keyed<T>
where
for<'a> T: Key<'a>,
for<'a> <T as Key<'a>>::Key: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&self.0.key(), &other.0.key())
}
}
But this solution does not seem to work:
fn main() {
let x: Keyed<NonBorrowedKey<i32, i32>> = Keyed(NonBorrowedKey { key: 3, value: 2 });
let y: Keyed<NonBorrowedKey<i32, i32>> = Keyed(NonBorrowedKey { key: 3, value: 5 });
PartialEq::eq(&x, &y);
}
I got the following error from the code above:
can't compare `<NonBorrowedKey<i32, i32> as Key<'a>>::Key` with `<NonBorrowedKey<i32, i32> as Key<'a>>::Key`
the trait `for<'a> std::cmp::PartialEq` is not implemented for `<NonBorrowedKey<i32, i32> as Key<'a>>::Key`
required because of the requirements on the impl of `std::cmp::PartialEq` for `Keyed<NonBorrowedKey<i32, i32>>`
required by `std::cmp::PartialEq::eq`
You can try the codes here.
Why this error happens?