@@ -541,9 +541,25 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
541
541
pub fn is_uninit_value_valid_for_ty < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> bool {
542
542
cx. tcx
543
543
. check_validity_requirement ( ( ValidityRequirement :: Uninit , cx. param_env . and ( ty) ) )
544
- // For types containing generic parameters we cannot get a layout to check.
545
- // Therefore, we are conservative and assume that they don't allow uninit.
546
- . unwrap_or ( false )
544
+ . unwrap_or_else ( |_| is_uninit_value_valid_for_ty_fallback ( cx, ty) )
545
+ }
546
+
547
+ /// A fallback for polymorphic types, which are not supported by `check_validity_requirement`.
548
+ fn is_uninit_value_valid_for_ty_fallback < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> bool {
549
+ match * ty. kind ( ) {
550
+ // The array length may be polymorphic, let's try the inner type.
551
+ ty:: Array ( component, _) => is_uninit_value_valid_for_ty ( cx, component) ,
552
+ // Peek through tuples and try their fallbacks.
553
+ ty:: Tuple ( types) => types. iter ( ) . all ( |ty| is_uninit_value_valid_for_ty ( cx, ty) ) ,
554
+ // Unions are always fine right now.
555
+ // This includes MaybeUninit, the main way people use uninitialized memory.
556
+ ty:: Adt ( adt, _) if adt. is_union ( ) => true ,
557
+ // For ADTs, we could look at all fields just like for tuples, but that's potentially
558
+ // exponential, so let's avoid doing that for now. Code doing that is sketchy enough to
559
+ // just use an `#[allow()]`.
560
+ // For the rest, conservatively assume that they cannot be uninit.
561
+ _ => false ,
562
+ }
547
563
}
548
564
549
565
/// Gets an iterator over all predicates which apply to the given item.
0 commit comments