Dyn Any downcasting for Arc?

⚓ Rust    📅 2025-10-13    👤 surdeus    👁️ 2      

surdeus

This may be more an IRLO question, not sure:

Downcasting dyn Any is implemented for plain dyn Any and Box<dyn Any>. But not for Arc<dyn Any> (or other smart pointers).

What is the reasoning here? Would the memory layout be different? As I understand it, the vtable is stored in the fat pointer, which is outside the Arc. So why wouldn't it be possible to downcast?

While I can downcast the inner reference of course, that doesn't let me get an Arc<ConcreteType> back, which complicates my API significantly. What I'm trying to do is a type-erased in-process pub-sub bus, where the topic is the type-id of message. I have code like:

pub trait Message: Any + Send + Sync + 'static {}

impl<T> Message for T where T: Send + Sync + Any + 'static {}

// ...

impl Client {
    // This doesn't work, we can't return a reference to to the Arc that goes out of scope...
    pub async fn receive<Type: Message>(&mut self) -> Option<&Type> {
        if let Some(rx) = self.subscriptions.get_mut(&std::any::TypeId::of::<Type>()) {
            let msg = rx.recv().await.ok();
            msg.map(|m| {
                // Side question: Why do I even need to up-cast to the base trait? Shouldn't downcast_ref exist on &*m?
                // Not that it would help, since I need to return a Option<Arc<Type>>...
                let any = &*m as &dyn Any;
                any.downcast_ref::<Type>()
            })
            .flatten()
        } else {
            None
        }
    }
}

1 post - 1 participant

Read full topic

🏷️ Rust_feed