@@ -541,9 +541,25 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
541541pub fn is_uninit_value_valid_for_ty < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> bool {
542542 cx. tcx
543543 . 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+ // For ADTs, we could look at all fields just like for tuples, but that's potentially
557+ // exponential, so let's avoid doing that for now. Code doing that is sketchy enough to
558+ // just use an `#[allow()]`.
559+ ty:: Adt ( adt, _) => adt. is_union ( ) ,
560+ // For the rest, conservatively assume that they cannot be uninit.
561+ _ => false ,
562+ }
547563}
548564
549565/// Gets an iterator over all predicates which apply to the given item.
0 commit comments