#![feature(trait_upcasting)] //@ check-fail // // issue: //! This would segfault at runtime. pub trait SupSupA { fn method(&self) {} } pub trait SupSupB {} impl SupSupA for T {} impl SupSupB for T {} pub trait Super: SupSupA + SupSupB {} pub trait Unimplemented {} pub trait Trait: Super + Super { fn missing_method(&self) where T1: Unimplemented, { } } impl Super for S {} impl Trait for S {} #[inline(never)] pub fn user1() -> &'static dyn Trait { &() /* VTABLE: .L__unnamed_2: .quad core::ptr::drop_in_place<()> .asciz "\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000" .quad example::SupSupA::method .quad .L__unnamed_4 // SupSupB vtable (pointer) .zero 8 // null pointer for missing_method */ } #[inline(never)] pub fn user2() -> &'static dyn Trait { &() /* VTABLE: .L__unnamed_3: .quad core::ptr::drop_in_place<()> .asciz "\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000" .quad example::SupSupA::method .quad .L__unnamed_4 // SupSupB vtable (pointer) .quad .L__unnamed_5 // Super vtable (pointer) .zero 8 // null pointer for missing_method */ } fn main() { let p: *const dyn Trait = &(); let p = p as *const dyn Trait; // <- this is bad! //~^ error: casting `*const dyn Trait` as `*const dyn Trait` is invalid let p = p as *const dyn Super; // <- this upcast accesses improper vtable entry // accessing from L__unnamed_2 the position for the 'Super vtable (pointer)', // thus reading 'null pointer for missing_method' let p = p as *const dyn SupSupB; // <- this upcast dereferences (null) pointer from that entry // to read the SupSupB vtable (pointer) // SEGFAULT println!("{:?}", p); }