mem::transmute::<Box<Any + Send + Sync>, Box<T>>?

If I know that I put in a Box<T>, but stored the Box as Box<Any + Send + Sync> (heterogeneous collection), is it "safe"-ish to transmute that back into a Box<T>?

I have a Vec<Box<Trait>>, where Trait includes a method that returns Box<Any + Send + Sync> and a method that accepts the same Box<Any + Send + Sync> returned by the previous method. (Parallel Vec<Box<Any>> of the same size keeps track of these).

In the impl of Trait, is it safe for me to return Box<T> and then later transmute the incoming Box<Any + Send + Sync> to Box<T>? I feel like this is probably valid, and the unsafe block is required because it's impossible to guarantee at compile time that the incoming Box<Any + Send + Sync> is the same as the one returned by a different function. But if I can make that guarantee at runtime, then the unsafe transmute should be fine. Am I missing something?

Alternatively, of course, is there a better way to do what I'm doing? (Store data from Trait objects that is later returned to the same Trait objects?)

You can downcast a trait object to its concrete type using Box<dyn Any>::downcast()

1 Like

Oh yeah, I remember seeing that before. I forgot to mention that the Any is actually Any + Send + Sync (edited to add in the original question), on which downcast does not seem to be implemented.

That confuses me slightly, since downcast works on just Any, and a type that's Any + Send + Sync is also Any. Is there something about Sync that would make a difference here?

You'll need to coerce the Box<dyn Any + Send + Sync + 'static> to a trait object without Sync right before downcasting:

fn main ()
    use ::core::any::Any;

    let x: Box<dyn Any + Send + Sync + 'static> =

    let x: Box<u8> =
        Box::<dyn Any + 'static>::downcast(x)

That looks much better than transmute. I didn't realise I could call the downcast function like that, but in retrospect it makes sense. Thanks all!

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