68 lines
1.6 KiB
Rust
68 lines
1.6 KiB
Rust
//@ 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();
|
|
}
|