Cast from Concrete to Any and subtraits

I didn't really review the code after I read it was based on type_name, but let's see if I can make sense of it...

unsafe fn cast_to_mut(&mut self, trait_num: usize) -> usize {
// ...
                            union U {
                                ptr: *mut *mut dyn AnyTrait,
                                raw_ptr: usize,
                            }
/* X */                     let t = &mut *(self as *mut dyn AnyTrait);
                            let tmp = U {
/* Y */                         ptr: &mut (t as *mut dyn AnyTrait),
                            };
/* Z */                     return tmp.raw_ptr;

Your roundtripping through unions, like at Z, is basically just an indirect way to transmute or transmute_copy. I'd probably avoid usize and instead go with [*const (); 2] or such to avoid some ambiguity around provenance.

At X, that's just

let t: &mut dyn AnyTrait = self;

But most importantly, at Y you're storing the address of a temporary. The pointed-to place will be invalidated at the end of the block. So your downcast methods are performing UB by reading through the returned pointer.

You can presumably run your tests with Miri to see this. You can run Miri in the playground until Tools, top right.


So the idea seems to be that the macro generates a way to create a type-erased pointer to the implementing type as &Self or as &dyn Trait for some set of specified traits. Getting a valid pointer isn't a problem, though type erasing it is a challenge. Then dyn AnyTrait can generically downcast based on that type erased pointer.

It turns out that you can destructure and restructure potentially wide pointers on stable. Layout is more the concern than size, as the FCP'd safety invariant is that the metadata is a valid word-aligned pointer. But there are enough pointer-manipulating methods available that the layout can be determined too.

I didn't make any compile-time considerations, but here's a POC that follows the basic shape of your trait as I understand it.

It's quite possible that there's a crate which does this or something analogous; I didn't go looking.