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> =
        Box::new(42_u8)
    ;

    let x: Box<u8> =
        Box::<dyn Any + 'static>::downcast(x)
            .unwrap()
    ;
    dbg!(x);
}
2 Likes

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!