Greetings!
This is my first post here.. so please help me make this more clear if you find it is not
I've been working on an interesting problem, where I need to cast a pointer to a trait object (&dyn T) to a point of another trait object (&dyn U), where U is a sub-trait of T. Here is a playground link illustrating the problem, and a potential solution: Rust Playground
Here's the meat of the transformation, where T = SuperTrait, and U = SubTrait, and ConcreteType implements both T and U. The type FatPtr is an alias for (usize, usize).
impl std::convert::TryFrom<&dyn SuperTrait> for &dyn SubTrait {
type Error = &'static str;
fn try_from(super_trait: &dyn SuperTrait) -> Result<Self, Self::Error> {
let fake_sub_trait = MaybeUninit::<ConcreteType>::uninit();
let (_data_ptr, vtable_ptr) = unsafe { transmute::<&dyn SubTrait, FatPtr>(&fake_sub_trait.assume_init() as &dyn SubTrait) };
let (data_ptr, _vtable_ptr) = unsafe { transmute::<&dyn SuperTrait, FatPtr>(super_trait) };
let sub_trait = unsafe { transmute::<FatPtr, &dyn SubTrait>((data_ptr, vtable_ptr)) };
Ok(sub_trait)
}
}
I'm well aware just how unsafe this is.. but I'm most afraid of this line of code:
let (_data_ptr, vtable_ptr) = unsafe { transmute::<&dyn SubTrait, FatPtr>(&fake_sub_trait.assume_init() as &dyn SubTrait) };
My fears stem from this piece of documentation concerning std::mem::MaybeUninit, found here: MaybeUninit in std::mem - Rust
My question to you is, given &dyn SuperTrait is really a pointer to a ConcreteType that was casted, does this line of code above still trigger undefined behavior?
Thanks for reading!