| //@ known-bug: #114484 |
| use std::marker::PhantomData; |
| |
| trait MyTrait { |
| fn virtualize(&self) -> &dyn MyTrait; |
| } |
| |
| struct VirtualWrapper<T, const L: u8>(T); |
| |
| impl<T, const L: u8> VirtualWrapper<T, L> { |
| pub fn wrap(value: &T) -> &Self { |
| unsafe { &*(value as *const T as *const Self) } |
| } |
| } |
| |
| impl<T: MyTrait + 'static, const L: u8> MyTrait for VirtualWrapper<T, L> { |
| fn virtualize(&self) -> &dyn MyTrait { |
| unsafe { virtualize_my_trait(L, self) } |
| // unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem |
| } |
| } |
| |
| const unsafe fn virtualize_my_trait<T>(level: u8, obj: &T) -> &dyn MyTrait |
| where |
| T: MyTrait + 'static, |
| { |
| const fn gen_vtable_ptr<T, const L: u8>() -> *const () |
| where |
| T: MyTrait + 'static, |
| { |
| let [_, vtable] = unsafe { |
| std::mem::transmute::<*const dyn MyTrait, [*const (); 2]>(std::ptr::null::< |
| VirtualWrapper<T, L>, |
| >()) |
| }; |
| vtable |
| } |
| |
| struct Vtable<T>(PhantomData<T>); |
| |
| impl<T> Vtable<T> |
| where |
| T: MyTrait + 'static, |
| { |
| const LEVELS: [*const (); 2] = [gen_vtable_ptr::<T, 1>(), gen_vtable_ptr::<T, 2>()]; |
| } |
| |
| let vtable = Vtable::<T>::LEVELS[(level != 0) as usize]; |
| |
| let data = obj as *const T as *const (); |
| let ptr: *const dyn MyTrait = std::mem::transmute([data, vtable]); |
| |
| &*ptr |
| } |
| |
| struct SomeData<const N: usize>([u8; N]); |
| |
| impl<const N: usize> MyTrait for SomeData<N> { |
| fn virtualize(&self) -> &dyn MyTrait { |
| VirtualWrapper::<Self, 0>::wrap(self) |
| } |
| } |
| |
| fn main() { |
| let test = SomeData([0; 256]); |
| test.virtualize(); |
| } |