I have the following code, that works fine
use dyn_clone::*;
trait MyTrait<V>: DynClone {}
#[derive(Clone)]
struct MyStruct<V> (core::marker::PhantomData<V>);
impl<V: Clone> MyTrait<V> for MyStruct<V> {}
#[repr(transparent)]
struct SmartPtr<V>(std::sync::Arc<dyn MyTrait<V> + 'static>);
impl<V> SmartPtr<V> {
pub fn borrow_dyn(&self) -> &dyn MyTrait<V> {
&*self.0
}
}
However, I am trying to make the fat pointer into a thin pointer for performance reasons, and I have gotten into a pickle. Below I changed SmartPointer
to something else... (For simplicity in this example, I'm just assuming it can only be one type. In reality it's an enum, but the same problem happens)
use dyn_clone::*;
trait MyTrait<V>: DynClone {}
#[derive(Clone)]
struct MyStruct<V> (core::marker::PhantomData<V>);
impl<V: Clone> MyTrait<V> for MyStruct<V> {}
struct SmartPtr<V>(Box<MyStruct<V>>);
impl<V> SmartPtr<V> {
// I need to call this from a `Drop` impl, so a bound is no good
// However I know that `SmartPtr<V>` cannot be created unless V: Clone
pub fn borrow_dyn(&self) -> &dyn MyTrait<V> {
&*self.0 as &dyn MyTrait<V>
}
}
The issue with bounding the SmartPtr
impl explicitly is that I can't use these methods in Drop. So I want to achieve the same implicit bounding as the Arc-based implementation.
I think the Arc-based impl actually constructs the vtable pointer when the V type is bounded, and stores that vtable pointer, which can be retrieved without the bound. OTOH, my Box-based impl doesn't have a vtable pointer until it's too late...
So somehow I need to make sure the vtable gets built in advance, and stash the metadata somewhere. But I'm hesitant to go too low-level until I've explored what can be done in the less error-prone corners of the language.
Thanks in advance for any ideas.