use std::{ any::TypeId, marker::PhantomData, mem::{self, ManuallyDrop}, }; // SAFETY: this function does not compare lifetimes. Values returned as `Ok` // may have their lifetimes extended. pub(super) unsafe fn try_transmute(x: Src) -> Result { if nonstatic_typeid::() == TypeId::of::() { let x = ManuallyDrop::new(x); // SAFETY: we have checked that the types are the same. Ok(unsafe { mem::transmute_copy::(&x) }) } else { Err(x) } } // https://github.com/dtolnay/typeid/blob/b06a3c08a0eaccc7df6091ade1ae4e3fb53609d5/src/lib.rs#L197-L222 #[inline(always)] fn nonstatic_typeid() -> TypeId where T: ?Sized, { trait NonStaticAny { fn get_type_id(&self) -> TypeId where Self: 'static; } impl NonStaticAny for PhantomData { #[inline(always)] fn get_type_id(&self) -> TypeId where Self: 'static, { TypeId::of::() } } let phantom_data = PhantomData::; NonStaticAny::get_type_id(unsafe { mem::transmute::<&dyn NonStaticAny, &(dyn NonStaticAny + 'static)>(&phantom_data) }) }