// run-pass // ignore-wasm32-bare compiled with panic=abort by default // This test checks panic emitted from `mem::{uninitialized,zeroed}`. #![feature(never_type)] #![allow(deprecated, invalid_value)] use std::{ mem::{self, MaybeUninit}, panic, ptr::NonNull, }; #[allow(dead_code)] struct Foo { x: u8, y: !, } enum Bar {} #[allow(dead_code)] enum OneVariant { Variant(i32) } fn test_panic_msg(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { let err = panic::catch_unwind(op).err(); assert_eq!( err.as_ref().and_then(|a| a.downcast_ref::()).map(|s| &**s), Some(msg) ); } fn main() { unsafe { // Uninitialized types test_panic_msg( || mem::uninitialized::(), "attempted to instantiate uninhabited type `!`" ); test_panic_msg( || mem::zeroed::(), "attempted to instantiate uninhabited type `!`" ); test_panic_msg( || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `!`" ); test_panic_msg( || mem::uninitialized::(), "attempted to instantiate uninhabited type `Foo`" ); test_panic_msg( || mem::zeroed::(), "attempted to instantiate uninhabited type `Foo`" ); test_panic_msg( || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `Foo`" ); test_panic_msg( || mem::uninitialized::(), "attempted to instantiate uninhabited type `Bar`" ); test_panic_msg( || mem::zeroed::(), "attempted to instantiate uninhabited type `Bar`" ); test_panic_msg( || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `Bar`" ); // Types that do not like zero-initialziation test_panic_msg( || mem::uninitialized::(), "attempted to leave type `fn()` uninitialized, which is invalid" ); test_panic_msg( || mem::zeroed::(), "attempted to zero-initialize type `fn()`, which is invalid" ); test_panic_msg( || mem::uninitialized::<*const dyn Send>(), "attempted to leave type `*const dyn std::marker::Send` uninitialized, which is invalid" ); test_panic_msg( || mem::zeroed::<*const dyn Send>(), "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid" ); test_panic_msg( || mem::uninitialized::<(NonNull, u32, u32)>(), "attempted to leave type `(std::ptr::NonNull, u32, u32)` uninitialized, \ which is invalid" ); test_panic_msg( || mem::zeroed::<(NonNull, u32, u32)>(), "attempted to zero-initialize type `(std::ptr::NonNull, u32, u32)`, \ which is invalid" ); test_panic_msg( || mem::uninitialized::(), "attempted to leave type `bool` uninitialized, which is invalid" ); // Some things that should work. let _val = mem::zeroed::(); let _val = mem::zeroed::(); let _val = mem::zeroed::>(); let _val = mem::zeroed::>>(); let _val = mem::uninitialized::>(); // We don't panic for these just to be conservative. They are UB as of now (2019-11-09). let _val = mem::uninitialized::(); let _val = mem::uninitialized::<*const ()>(); } }