For complicated reasons, I need to create type-erased versions of some objects, that implement a non-object-safe trait.
A simplified version of my type looks like:
pub trait AnyState: Any {
fn dyn_clone(&self) -> Box<dyn AnyState>;
fn dyn_eq(&self, other: &Box<dyn AnyState>) -> bool;
}
impl<T> AnyState for T
where
T: Clone + PartialEq + 'static,
{
fn dyn_clone(&self) -> Box<dyn AnyState> {
let b = Box::new(self.clone());
}
fn dyn_eq(&self, other: &Box<dyn AnyState>) -> bool {
if let Some(other) = Any::downcast_ref::<Self>(other) {
other.eq(self)
} else {
false
}
}
}
pub struct AnyStateBox {
value: Box<dyn AnyState>,
}
impl AnyStateBox {
pub fn new(state: impl AnyState) -> Self {
AnyStateBox {
value: Box::new(state),
}
}
}
impl Clone for AnyStateBox {
fn clone(&self) -> Self {
AnyStateBox {
value: self.value.dyn_clone(),
}
}
}
impl PartialEq for AnyStateBox {
fn eq(&self, other: &Self) -> bool {
self.value.dyn_eq(&other.value)
}
}
But then, if I run
let state1 = AnyStateBox::new(42);
let state2 = state1.clone();
assert_eq!(state1, state2);
The test immediately fails; after some searching it turns out that the TypeId
of the clone is different from the TypeId
of the original, even though they're both i32
.
Is there a way to fix this? I really need the type erasure for my design.