| // 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, ManuallyDrop}, |
| panic, |
| ptr::NonNull, |
| num, |
| }; |
| |
| #[allow(dead_code)] |
| struct Foo { |
| x: u8, |
| y: !, |
| } |
| |
| enum Bar {} |
| |
| #[allow(dead_code)] |
| enum OneVariant { Variant(i32) } |
| |
| // An enum with ScalarPair layout |
| #[allow(dead_code)] |
| enum LR { |
| Left(i64), |
| Right(i64), |
| } |
| #[allow(dead_code, non_camel_case_types)] |
| enum LR_NonZero { |
| Left(num::NonZeroI64), |
| Right(num::NonZeroI64), |
| } |
| |
| fn test_panic_msg<T>(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::<String>()).map(|s| &**s), |
| Some(msg) |
| ); |
| } |
| |
| fn main() { |
| unsafe { |
| // Uninhabited 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::<Foo>(), |
| "attempted to instantiate uninhabited type `Foo`" |
| ); |
| test_panic_msg( |
| || mem::zeroed::<Foo>(), |
| "attempted to instantiate uninhabited type `Foo`" |
| ); |
| test_panic_msg( |
| || MaybeUninit::<Foo>::uninit().assume_init(), |
| "attempted to instantiate uninhabited type `Foo`" |
| ); |
| |
| test_panic_msg( |
| || mem::uninitialized::<Bar>(), |
| "attempted to instantiate uninhabited type `Bar`" |
| ); |
| test_panic_msg( |
| || mem::zeroed::<Bar>(), |
| "attempted to instantiate uninhabited type `Bar`" |
| ); |
| test_panic_msg( |
| || MaybeUninit::<Bar>::uninit().assume_init(), |
| "attempted to instantiate uninhabited type `Bar`" |
| ); |
| |
| // Types that do not like zero-initialziation |
| test_panic_msg( |
| || mem::uninitialized::<fn()>(), |
| "attempted to leave type `fn()` uninitialized, which is invalid" |
| ); |
| test_panic_msg( |
| || mem::zeroed::<fn()>(), |
| "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" |
| ); |
| |
| /* FIXME(#66151) we conservatively do not error here yet. |
| test_panic_msg( |
| || mem::uninitialized::<LR_NonZero>(), |
| "attempted to leave type `LR_NonZero` uninitialized, which is invalid" |
| ); |
| test_panic_msg( |
| || mem::zeroed::<LR_NonZero>(), |
| "attempted to zero-initialize type `LR_NonZero`, which is invalid" |
| ); |
| |
| test_panic_msg( |
| || mem::uninitialized::<ManuallyDrop<LR_NonZero>>(), |
| "attempted to leave type `std::mem::ManuallyDrop<LR_NonZero>` uninitialized, \ |
| which is invalid" |
| ); |
| test_panic_msg( |
| || mem::zeroed::<ManuallyDrop<LR_NonZero>>(), |
| "attempted to zero-initialize type `std::mem::ManuallyDrop<LR_NonZero>`, \ |
| which is invalid" |
| ); |
| |
| test_panic_msg( |
| || mem::uninitialized::<(NonNull<u32>, u32, u32)>(), |
| "attempted to leave type `(std::ptr::NonNull<u32>, u32, u32)` uninitialized, \ |
| which is invalid" |
| ); |
| test_panic_msg( |
| || mem::zeroed::<(NonNull<u32>, u32, u32)>(), |
| "attempted to zero-initialize type `(std::ptr::NonNull<u32>, u32, u32)`, \ |
| which is invalid" |
| ); |
| */ |
| |
| // Types that can be zero, but not uninit. |
| test_panic_msg( |
| || mem::uninitialized::<bool>(), |
| "attempted to leave type `bool` uninitialized, which is invalid" |
| ); |
| test_panic_msg( |
| || mem::uninitialized::<LR>(), |
| "attempted to leave type `LR` uninitialized, which is invalid" |
| ); |
| test_panic_msg( |
| || mem::uninitialized::<ManuallyDrop<LR>>(), |
| "attempted to leave type `std::mem::ManuallyDrop<LR>` uninitialized, which is invalid" |
| ); |
| |
| // Some things that should work. |
| let _val = mem::zeroed::<bool>(); |
| let _val = mem::zeroed::<LR>(); |
| let _val = mem::zeroed::<ManuallyDrop<LR>>(); |
| let _val = mem::zeroed::<OneVariant>(); |
| let _val = mem::zeroed::<Option<&'static i32>>(); |
| let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>(); |
| let _val = mem::uninitialized::<MaybeUninit<bool>>(); |
| |
| // These are UB because they have not been officially blessed, but we await the resolution |
| // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing |
| // anything about that. |
| let _val = mem::uninitialized::<i32>(); |
| let _val = mem::uninitialized::<*const ()>(); |
| } |
| } |