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
fnpointers 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>, }