Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions compiler/rustc_target/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,8 +1162,13 @@ 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() {
Expand Down
102 changes: 101 additions & 1 deletion src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,59 +65,111 @@ fn main() {
|| mem::uninitialized::<!>(),
"attempted to instantiate uninhabited type `!`"
);
test_panic_msg(
|| mem::uninitialized::<[!; 2]>(),
"attempted to instantiate uninhabited type `[!; 2]`"
);
test_panic_msg(
|| mem::zeroed::<!>(),
"attempted to instantiate uninhabited type `!`"
);
test_panic_msg(
|| mem::zeroed::<[!; 2]>(),
"attempted to instantiate uninhabited type `[!; 2]`"
);
test_panic_msg(
|| MaybeUninit::<!>::uninit().assume_init(),
"attempted to instantiate uninhabited type `!`"
);
test_panic_msg(
|| MaybeUninit::<[!; 2]>::uninit().assume_init(),
"attempted to instantiate uninhabited type `[!; 2]`"
);

test_panic_msg(
|| mem::uninitialized::<Foo>(),
"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>(),
"attempted to instantiate uninhabited type `Foo`"
);
test_panic_msg(
|| mem::zeroed::<[Foo; 2]>(),
"attempted to instantiate uninhabited type `[Foo; 2]`"
);
test_panic_msg(
|| MaybeUninit::<Foo>::uninit().assume_init(),
"attempted to instantiate uninhabited type `Foo`"
);
test_panic_msg(
|| MaybeUninit::<[Foo; 2]>::uninit().assume_init(),
"attempted to instantiate uninhabited type `[Foo; 2]`"
);

test_panic_msg(
|| mem::uninitialized::<Bar>(),
"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>(),
"attempted to instantiate uninhabited type `Bar`"
);
test_panic_msg(
|| mem::zeroed::<[Bar; 4]>(),
"attempted to instantiate uninhabited type `[Bar; 4]`"
);
test_panic_msg(
|| MaybeUninit::<Bar>::uninit().assume_init(),
"attempted to instantiate uninhabited type `Bar`"
);
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::<fn()>(),
"attempted to leave type `fn()` uninitialized, 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()>(),
"attempted to zero-initialize type `fn()`, 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>(),
"attempted to leave type `*const dyn std::marker::Send` uninitialized, 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>(),
"attempted to zero-initialize type `*const dyn std::marker::Send`, 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(
Expand Down Expand Up @@ -146,39 +198,73 @@ fn main() {
"attempted to leave type `(std::ptr::NonNull<u32>, u32, u32)` uninitialized, \
which is invalid"
);
test_panic_msg(
|| mem::uninitialized::<[(NonNull<u32>, u32, u32); 2]>(),
"attempted to leave type `[(std::ptr::NonNull<u32>, u32, u32); 2]` 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"
);
test_panic_msg(
|| mem::zeroed::<[(NonNull<u32>, u32, u32); 2]>(),
"attempted to zero-initialize type `[(std::ptr::NonNull<u32>, u32, u32); 2]`, \
which is invalid"
);

test_panic_msg(
|| mem::uninitialized::<OneVariant_NonZero>(),
"attempted to leave type `OneVariant_NonZero` uninitialized, \
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>(),
"attempted to zero-initialize type `OneVariant_NonZero`, \
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::<NoNullVariant>(),
"attempted to leave type `NoNullVariant` uninitialized, \
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>(),
"attempted to zero-initialize type `NoNullVariant`, \
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(
|| mem::uninitialized::<bool>(),
"attempted to leave type `bool` 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>(),
"attempted to leave type `LR` uninitialized, which is invalid"
Expand All @@ -190,17 +276,31 @@ fn main() {

// Some things that should work.
let _val = mem::zeroed::<bool>();
let _val = mem::zeroed::<[bool; 4]>();
let _val = mem::zeroed::<LR>();
let _val = mem::zeroed::<[LR; 8]>();
let _val = mem::zeroed::<ManuallyDrop<LR>>();
let _val = mem::zeroed::<[ManuallyDrop<LR>; 16]>();
let _val = mem::zeroed::<OneVariant>();
let _val = mem::zeroed::<[OneVariant; 2]>();
let _val = mem::zeroed::<Option<&'static i32>>();
let _val = mem::zeroed::<[Option<&'static i32>; 3]>();
let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>();
let _val = mem::zeroed::<[MaybeUninit<NonNull<u32>>; 32]>();
let _val = mem::zeroed::<[!; 0]>();
let _val = mem::uninitialized::<MaybeUninit<bool>>();
let _val = mem::uninitialized::<[MaybeUninit<bool>; 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 <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing
// anything about that.
let _val = mem::uninitialized::<i32>();
let _val = mem::uninitialized::<[i32; 1]>();
let _val = mem::uninitialized::<*const ()>();
let _val = mem::uninitialized::<[*const (); 2]>();
}
}