rust/tests/crashes/114484.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

68 lines
1.6 KiB
Rust
Raw Normal View History

//@ 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();
}