Ideas for constructing a fat (dyn) pointer

⚓ rust    📅 2025-05-15    👤 surdeus    👁️ 5      

surdeus

Warning

This post was published 47 days ago. The information described in this article may have changed.

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.

2 posts - 2 participants

Read full topic

🏷️ rust_feed