Arc::downcast without the requirement for Send + Sync

I'm working on an interface that can accept user defined types and I want it to work for both Send + Sync and non-Send+Sync types. And for that I'm using and Arc.

The problem I have is that Arc::downcast Is implemented only for Any + Send + Sync + 'static and I need it for Any + 'static. Here's what I did:

pub fn downcast_arc<T>(arc: Arc<dyn Any>) -> Result<Arc<T>, Arc<dyn Any>>
        T: Any + 'static,
        if (*arc).is::<T>() {
            let ptr = Arc::into_raw(arc).cast::<T>();
            Ok(unsafe { Arc::from_raw(ptr) })
        } else {

It works, but is this safe?

It is.

  • (As safe as any TypeId-based (down)casting can be: there currently is a 1 in 2^64 that the TypeId hash collides with another type's, which would make Any::is return a false positive).

Indeed, Arc<dyn Any> = (Arc<Erased>, &'static <T as Any>::VTable); thanks to the vtable you get access to .type_id() which lets you "check" whether Erased used to be T. You then drop the vtable reference and cast Erased back to the T it presumably was. In the meantime, Arc::into_raw and Arc::from_raw have been working with pointers to the same data, so all is good.


This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.