diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index a43080b09e9a1..83f8c3dc138a6 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1162,8 +1162,11 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { // If we have not found an error yet, we need to recursively descend into fields. match &self.fields { FieldsShape::Primitive | FieldsShape::Union { .. } => {} - FieldsShape::Array { .. } => { - // FIXME(#66151): For now, we are conservative and do not check arrays. + FieldsShape::Array { count, .. } => { + if *count > 0 && !self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? { + // Found non empty array with a type that is unhappy about this kind of initialization + return Ok(false); + } } FieldsShape::Arbitrary { offsets, .. } => { for idx in 0..offsets.len() { diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 4a91198ab9f6f..4cf4df73a14e7 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -73,6 +73,18 @@ fn main() { || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `!`" ); + test_panic_msg( + || mem::uninitialized::<[!; 2]>(), + "attempted to instantiate uninhabited type `[!; 2]`" + ); + test_panic_msg( + || mem::zeroed::<[!; 2]>(), + "attempted to instantiate uninhabited type `[!; 2]`" + ); + test_panic_msg( + || MaybeUninit::<[!; 2]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[!; 2]`" + ); test_panic_msg( || mem::uninitialized::(), @@ -86,6 +98,18 @@ fn main() { || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `Foo`" ); + test_panic_msg( + || mem::uninitialized::<[Foo; 2]>(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + test_panic_msg( + || mem::zeroed::<[Foo; 2]>(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + test_panic_msg( + || MaybeUninit::<[Foo; 2]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); test_panic_msg( || mem::uninitialized::(), @@ -99,8 +123,20 @@ fn main() { || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `Bar`" ); + test_panic_msg( + || mem::uninitialized::<[Bar; 4]>(), + "attempted to instantiate uninhabited type `[Bar; 4]`" + ); + test_panic_msg( + || mem::zeroed::<[Bar; 4]>(), + "attempted to instantiate uninhabited type `[Bar; 4]`" + ); + test_panic_msg( + || MaybeUninit::<[Bar; 4]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[Bar; 4]`" + ); - // Types that do not like zero-initialziation + // Types that do not like zero-initialization test_panic_msg( || mem::uninitialized::(), "attempted to leave type `fn()` uninitialized, which is invalid" @@ -109,6 +145,14 @@ fn main() { || mem::zeroed::(), "attempted to zero-initialize type `fn()`, which is invalid" ); + test_panic_msg( + || mem::uninitialized::<[fn(); 2]>(), + "attempted to leave type `[fn(); 2]` uninitialized, which is invalid" + ); + test_panic_msg( + || mem::zeroed::<[fn(); 2]>(), + "attempted to zero-initialize type `[fn(); 2]`, which is invalid" + ); test_panic_msg( || mem::uninitialized::<*const dyn Send>(), @@ -118,6 +162,16 @@ fn main() { || mem::zeroed::<*const dyn Send>(), "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid" ); + test_panic_msg( + || mem::uninitialized::<[*const dyn Send; 2]>(), + "attempted to leave type `[*const dyn std::marker::Send; 2]` uninitialized, \ + which is invalid" + ); + test_panic_msg( + || mem::zeroed::<[*const dyn Send; 2]>(), + "attempted to zero-initialize type `[*const dyn std::marker::Send; 2]`, \ + which is invalid" + ); /* FIXME(#66151) we conservatively do not error here yet. test_panic_msg( @@ -151,6 +205,16 @@ fn main() { "attempted to zero-initialize type `(std::ptr::NonNull, u32, u32)`, \ which is invalid" ); + test_panic_msg( + || mem::uninitialized::<[(NonNull, u32, u32); 2]>(), + "attempted to leave type `[(std::ptr::NonNull, u32, u32); 2]` uninitialized, \ + which is invalid" + ); + test_panic_msg( + || mem::zeroed::<[(NonNull, u32, u32); 2]>(), + "attempted to zero-initialize type `[(std::ptr::NonNull, u32, u32); 2]`, \ + which is invalid" + ); test_panic_msg( || mem::uninitialized::(), @@ -162,6 +226,16 @@ fn main() { "attempted to zero-initialize type `OneVariant_NonZero`, \ which is invalid" ); + test_panic_msg( + || mem::uninitialized::<[OneVariant_NonZero; 2]>(), + "attempted to leave type `[OneVariant_NonZero; 2]` uninitialized, \ + which is invalid" + ); + test_panic_msg( + || mem::zeroed::<[OneVariant_NonZero; 2]>(), + "attempted to zero-initialize type `[OneVariant_NonZero; 2]`, \ + which is invalid" + ); test_panic_msg( || mem::uninitialized::(), @@ -173,6 +247,16 @@ fn main() { "attempted to zero-initialize type `NoNullVariant`, \ which is invalid" ); + test_panic_msg( + || mem::uninitialized::<[NoNullVariant; 2]>(), + "attempted to leave type `[NoNullVariant; 2]` uninitialized, \ + which is invalid" + ); + test_panic_msg( + || mem::zeroed::<[NoNullVariant; 2]>(), + "attempted to zero-initialize type `[NoNullVariant; 2]`, \ + which is invalid" + ); // Types that can be zero, but not uninit. test_panic_msg( @@ -187,20 +271,47 @@ fn main() { || mem::uninitialized::>(), "attempted to leave type `std::mem::ManuallyDrop` uninitialized, which is invalid" ); + test_panic_msg( + || mem::uninitialized::<[bool; 2]>(), + "attempted to leave type `[bool; 2]` uninitialized, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<[LR; 2]>(), + "attempted to leave type `[LR; 2]` uninitialized, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<[ManuallyDrop; 2]>(), + "attempted to leave type `[std::mem::ManuallyDrop; 2]` uninitialized, \ + which is invalid" + ); // Some things that should work. let _val = mem::zeroed::(); + let _val = mem::zeroed::<[bool; 4]>(); let _val = mem::zeroed::(); + let _val = mem::zeroed::<[LR; 8]>(); let _val = mem::zeroed::>(); + let _val = mem::zeroed::<[ManuallyDrop; 16]>(); let _val = mem::zeroed::(); + let _val = mem::zeroed::<[OneVariant; 2]>(); let _val = mem::zeroed::>(); + let _val = mem::zeroed::<[Option<&'static i32>; 3]>(); let _val = mem::zeroed::>>(); + let _val = mem::zeroed::<[MaybeUninit>; 32]>(); + let _val = mem::zeroed::<[!; 0]>(); let _val = mem::uninitialized::>(); + let _val = mem::uninitialized::<[MaybeUninit; 1]>(); + let _val = mem::uninitialized::<[bool; 0]>(); + let _val = mem::uninitialized::<[!; 0]>(); + let _val = mem::uninitialized::<[fn(); 0]>(); + let _val = mem::uninitialized::<[*const dyn Send; 0]>(); // These are UB because they have not been officially blessed, but we await the resolution // of before doing // anything about that. let _val = mem::uninitialized::(); + let _val = mem::uninitialized::<[i32; 1]>(); let _val = mem::uninitialized::<*const ()>(); + let _val = mem::uninitialized::<[*const (); 2]>(); } }