about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_target/src/abi/mod.rs23
-rw-r--r--src/test/ui/intrinsics/panic-uninitialized-zeroed.rs40
2 files changed, 57 insertions, 6 deletions
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 4b565dd246f..3c1a2ea39d3 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -1135,16 +1135,31 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
             Abi::Scalar(s) => scalar_allows_raw_init(s),
             Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
             Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s),
-            Abi::Aggregate { .. } => true, // Cannot be excluded *right now*.
+            Abi::Aggregate { .. } => true, // Fields are checked below.
         };
         if !valid {
             // This is definitely not okay.
-            trace!("might_permit_raw_init({:?}, zero={}): not valid", self.layout, zero);
             return Ok(false);
         }
 
-        // If we have not found an error yet, we need to recursively descend.
-        // FIXME(#66151): For now, we are conservative and do not do this.
+        // 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::Arbitrary { offsets, .. } => {
+                for idx in 0..offsets.len() {
+                    let field = self.field(cx, idx).to_result()?;
+                    if !field.might_permit_raw_init(cx, zero)? {
+                        // We found a field that is unhappy with this kind of initialization.
+                        return Ok(false);
+                    }
+                }
+            }
+        }
+
+        // FIXME(#66151): For now, we are conservative and do not check `self.variants`.
         Ok(true)
     }
 }
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
index 02f8ecaa4ee..24474cabf1e 100644
--- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
+++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
@@ -3,7 +3,7 @@
 
 // This test checks panic emitted from `mem::{uninitialized,zeroed}`.
 
-#![feature(never_type)]
+#![feature(never_type, arbitrary_enum_discriminant)]
 #![allow(deprecated, invalid_value)]
 
 use std::{
@@ -24,6 +24,20 @@ enum Bar {}
 #[allow(dead_code)]
 enum OneVariant { Variant(i32) }
 
+#[allow(dead_code, non_camel_case_types)]
+enum OneVariant_NonZero {
+    Variant(i32, i32, num::NonZeroI32),
+    DeadVariant(Bar),
+}
+
+// An `Aggregate` abi enum where 0 is not a valid discriminant.
+#[allow(dead_code)]
+#[repr(i32)]
+enum NoNullVariant {
+    Variant1(i32, i32) = 1,
+    Variant2(i32, i32) = 2,
+}
+
 // An enum with ScalarPair layout
 #[allow(dead_code)]
 enum LR {
@@ -125,6 +139,7 @@ fn main() {
             "attempted to zero-initialize type `std::mem::ManuallyDrop<LR_NonZero>`, \
              which is invalid"
         );
+        */
 
         test_panic_msg(
             || mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
@@ -136,7 +151,28 @@ fn main() {
             "attempted to zero-initialize type `(std::ptr::NonNull<u32>, u32, u32)`, \
                 which is invalid"
         );
-        */
+
+        test_panic_msg(
+            || mem::uninitialized::<OneVariant_NonZero>(),
+            "attempted to leave type `OneVariant_NonZero` 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::uninitialized::<NoNullVariant>(),
+            "attempted to leave type `NoNullVariant` uninitialized, \
+                which is invalid"
+        );
+        test_panic_msg(
+            || mem::zeroed::<NoNullVariant>(),
+            "attempted to zero-initialize type `NoNullVariant`, \
+                which is invalid"
+        );
 
         // Types that can be zero, but not uninit.
         test_panic_msg(