// This test contains code with incorrect vtables in a const context: // - from issue 86132: a trait object with invalid alignment caused an ICE in const eval, and now // triggers an error // - a similar test that triggers a previously-untested const UB error: emitted close to the above // error, it checks the correctness of the size // // As is, this code will only hard error when the constants are used, and the errors are emitted via // the `#[allow]`-able `const_err` lint. However, if the transparent wrapper technique to prevent // reborrows is used -- from `ub-wide-ptr.rs` -- these two errors reach validation and would trigger // ICEs as tracked by #86193. So we also use the transparent wrapper to verify proper validation // errors are emitted instead of ICEs. // stderr-per-bitwidth // normalize-stderr-test "alloc\d+" -> "allocN" trait Trait {} const INVALID_VTABLE_ALIGNMENT: &dyn Trait = unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; //~^ ERROR evaluation of constant value failed //~| does not point to a vtable const INVALID_VTABLE_SIZE: &dyn Trait = unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; //~^ ERROR evaluation of constant value failed //~| does not point to a vtable #[repr(transparent)] struct W(T); fn drop_me(_: *mut usize) {} const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) }; //~^^ ERROR it is undefined behavior to use this value //~| expected a vtable pointer const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) }; //~^^ ERROR it is undefined behavior to use this value //~| expected a vtable pointer // Even if the vtable has a fn ptr and a reasonable size+align, it still does not work. const INVALID_VTABLE_UB: W<&dyn Trait> = unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1usize))) }; //~^^ ERROR it is undefined behavior to use this value //~| expected a vtable pointer // Trying to access the data in a vtable does not work, either. #[derive(Copy, Clone)] struct Wide<'a>(&'a Foo, &'static VTable); struct VTable { drop: Option fn(&'a mut Foo)>, size: usize, align: usize, bar: for<'a> fn(&'a Foo) -> u32, } trait Bar { fn bar(&self) -> u32; } struct Foo { foo: u32, bar: bool, } impl Bar for Foo { fn bar(&self) -> u32 { self.foo } } impl Drop for Foo { fn drop(&mut self) { assert!(!self.bar); self.bar = true; println!("dropping Foo"); } } #[repr(C)] union Transmute { t: T, u: U, } const FOO: &dyn Bar = &Foo { foo: 128, bar: false }; const G: Wide = unsafe { Transmute { t: FOO }.u }; //~^ ERROR it is undefined behavior to use this value //~| encountered a dangling reference // (it is dangling because vtables do not contain memory that can be dereferenced) fn main() {}