Is it possible to implement PartialEq
for a trait reference that returns true
for implementations instances that have the same inner content? The use case is the following snippet:
trait Trait: ::std::fmt::Debug {
fn method(&self, i32) -> ();
}
#[derive(Debug, PartialEq)]
struct Struct<'a> {
vec: Vec<&'a Trait>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
struct AnotherStruct {
int: i32
}
impl From<AnotherStruct> for i32 {
fn from(another_struct: AnotherStruct) -> i32 {
another_struct.int
}
}
impl<T> Trait for T
where
T: Copy + ::std::convert::Into<i32> + ::std::fmt::Debug
{
fn method(&self, value: i32) -> () {
let into: i32 = (*self).into();
println!("{} * {} = {}", into, value, into * value);
}
}
fn main() {
let a = Struct { vec: vec![&AnotherStruct { int: 5 }, &10i8] };
let b = Struct { vec: vec![&AnotherStruct { int: 5 }, &10i8] };
let c = Struct {
vec: vec![
&AnotherStruct { int: 3 },
&3i16,
&3u16,
&AnotherStruct { int: 3 }
]
};
assert_eq!(a, b);
assert_eq!(c.vec[0], c.vec[3]);
c.vec[1].method(5);
}
Can you see in the final lines that I trying to compare two instances of AnotherStruct
that have the same int
value? Unfortunately, this code doesn't compile (No PartialEq
for &Trait
) and since Trait
isn't a real object, it isn't possible to store traits references inside a vector using trait Trait: PartialEq
or trait Trait<'a>: PartialEq<&'a Self>
. Note: Vec<Box<Trait>>
isn't a viable option because of the runtime cost of memory allocation.
Knowing this limitations and also knowing that the method returning type can't be used as a unique discriminator, I am sharing some attempts I made in hope to shed some light for someone willing to help.
Use the method function pointer like Rust did for
fn
pointers to implementPartialEq
. After talking with two nice people on IRC about this strategy, they basically told me that I could try casting usingas *const _
but it isn't reliable because of possible code deduplication.// Compiler error: attempted to take value of method `method` on type `&&'a Trait + 'a` trait Trait { fn method(&self, i32) -> (); } impl<'a> PartialEq for &'a Trait { fn eq(&self, other: &Self) -> bool { *self.method as *const _ == *other.method as *const _ } } #[derive(PartialEq)] struct Struct<'a> { vec: Vec<&'a Trait>, }
Return the method as a function from another method and use it as a discriminator. This approach works but isn't very ergonomic and I don't consider it a solution.
trait Trait { fn another_method(&self) -> fn(i32); } impl<'a> PartialEq for &'a Trait { fn eq(&self, other: &Self) -> bool { self.another_method() == other.another_method() } } #[derive(PartialEq)] struct Struct<'a> { vec: Vec<&'a Trait>, }