@@ -894,6 +894,15 @@ impl Scalar {
894894 Scalar :: Union { .. } => true ,
895895 }
896896 }
897+
898+ /// Returns `true` if this type can be left uninit.
899+ #[ inline]
900+ pub fn is_uninit_valid ( & self ) -> bool {
901+ match * self {
902+ Scalar :: Initialized { .. } => false ,
903+ Scalar :: Union { .. } => true ,
904+ }
905+ }
897906}
898907
899908/// Describes how the fields of a type are located in memory.
@@ -1355,6 +1364,14 @@ pub struct PointeeInfo {
13551364 pub address_space : AddressSpace ,
13561365}
13571366
1367+ /// Used in `might_permit_raw_init` to indicate the kind of initialisation
1368+ /// that is checked to be valid
1369+ #[ derive( Copy , Clone , Debug ) ]
1370+ pub enum InitKind {
1371+ Zero ,
1372+ Uninit ,
1373+ }
1374+
13581375/// Trait that needs to be implemented by the higher-level type representation
13591376/// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality.
13601377pub trait TyAbiInterface < ' a , C > : Sized {
@@ -1461,26 +1478,37 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
14611478
14621479 /// Determines if this type permits "raw" initialization by just transmuting some
14631480 /// memory into an instance of `T`.
1464- /// `zero` indicates if the memory is zero-initialized, or alternatively
1465- /// left entirely uninitialized.
1481+ ///
1482+ /// `init_kind` indicates if the memory is zero-initialized or left uninitialized.
1483+ ///
1484+ /// `strict` is an opt-in debugging flag added in #97323 that enables more checks.
1485+ ///
14661486 /// This is conservative: in doubt, it will answer `true`.
14671487 ///
14681488 /// FIXME: Once we removed all the conservatism, we could alternatively
14691489 /// create an all-0/all-undef constant and run the const value validator to see if
14701490 /// this is a valid value for the given type.
1471- pub fn might_permit_raw_init < C > ( self , cx : & C , zero : bool ) -> bool
1491+ pub fn might_permit_raw_init < C > ( self , cx : & C , init_kind : InitKind , strict : bool ) -> bool
14721492 where
14731493 Self : Copy ,
14741494 Ty : TyAbiInterface < ' a , C > ,
14751495 C : HasDataLayout ,
14761496 {
14771497 let scalar_allows_raw_init = move |s : Scalar | -> bool {
1478- if zero {
1479- // The range must contain 0.
1480- s. valid_range ( cx) . contains ( 0 )
1481- } else {
1482- // The range must include all values.
1483- s. is_always_valid ( cx)
1498+ match init_kind {
1499+ InitKind :: Zero => {
1500+ // The range must contain 0.
1501+ s. valid_range ( cx) . contains ( 0 )
1502+ }
1503+ InitKind :: Uninit => {
1504+ if strict {
1505+ // The type must be allowed to be uninit (which means "is a union").
1506+ s. is_uninit_valid ( )
1507+ } else {
1508+ // The range must include all values.
1509+ s. is_always_valid ( cx)
1510+ }
1511+ }
14841512 }
14851513 } ;
14861514
@@ -1500,12 +1528,19 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
15001528 // If we have not found an error yet, we need to recursively descend into fields.
15011529 match & self . fields {
15021530 FieldsShape :: Primitive | FieldsShape :: Union { .. } => { }
1503- FieldsShape :: Array { .. } => {
1504- // FIXME(#66151): For now, we are conservative and do not check arrays.
1531+ FieldsShape :: Array { count, .. } => {
1532+ // FIXME(#66151): For now, we are conservative and do not check arrays by default.
1533+ if strict
1534+ && * count > 0
1535+ && !self . field ( cx, 0 ) . might_permit_raw_init ( cx, init_kind, strict)
1536+ {
1537+ // Found non empty array with a type that is unhappy about this kind of initialization
1538+ return false ;
1539+ }
15051540 }
15061541 FieldsShape :: Arbitrary { offsets, .. } => {
15071542 for idx in 0 ..offsets. len ( ) {
1508- if !self . field ( cx, idx) . might_permit_raw_init ( cx, zero ) {
1543+ if !self . field ( cx, idx) . might_permit_raw_init ( cx, init_kind , strict ) {
15091544 // We found a field that is unhappy with this kind of initialization.
15101545 return false ;
15111546 }
0 commit comments