@@ -10,7 +10,7 @@ use rustc_middle::mir::interpret::Scalar;
1010use rustc_middle:: mir:: { self , Const } ;
1111use rustc_middle:: thir:: { FieldPat , Pat , PatKind , PatRange , PatRangeBoundary } ;
1212use rustc_middle:: ty:: layout:: IntegerExt ;
13- use rustc_middle:: ty:: { self , OpaqueTypeKey , Ty , TyCtxt , TypeVisitableExt , VariantDef } ;
13+ use rustc_middle:: ty:: { self , FieldDef , OpaqueTypeKey , Ty , TyCtxt , TypeVisitableExt , VariantDef } ;
1414use rustc_session:: lint;
1515use rustc_span:: { ErrorGuaranteed , Span , DUMMY_SP } ;
1616use rustc_target:: abi:: { FieldIdx , Integer , VariantIdx , FIRST_VARIANT } ;
@@ -158,32 +158,19 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
158158 }
159159 }
160160
161- // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
162- // uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
163- // This lists the fields we keep along with their types.
164- pub ( crate ) fn list_variant_nonhidden_fields (
161+ pub ( crate ) fn variant_sub_tys (
165162 & self ,
166163 ty : RevealedTy < ' tcx > ,
167164 variant : & ' tcx VariantDef ,
168- ) -> impl Iterator < Item = ( FieldIdx , RevealedTy < ' tcx > , bool ) > + Captures < ' p > + Captures < ' _ >
165+ ) -> impl Iterator < Item = ( & ' tcx FieldDef , RevealedTy < ' tcx > ) > + Captures < ' p > + Captures < ' _ >
169166 {
170- let cx = self ;
171- let ty:: Adt ( adt, args) = ty. kind ( ) else { bug ! ( ) } ;
172- // Whether we must avoid matching the fields of this variant exhaustively.
173- let is_non_exhaustive = variant. is_field_list_non_exhaustive ( ) && !adt. did ( ) . is_local ( ) ;
174-
175- variant. fields . iter ( ) . enumerate ( ) . map ( move |( i, field) | {
176- let ty = field. ty ( cx. tcx , args) ;
167+ let ty:: Adt ( _, args) = ty. kind ( ) else { bug ! ( ) } ;
168+ variant. fields . iter ( ) . map ( move |field| {
169+ let ty = field. ty ( self . tcx , args) ;
177170 // `field.ty()` doesn't normalize after substituting.
178- let ty = cx. tcx . normalize_erasing_regions ( cx. param_env , ty) ;
179- let is_visible = adt. is_enum ( ) || field. vis . is_accessible_from ( cx. module , cx. tcx ) ;
180- let is_uninhabited = ( cx. tcx . features ( ) . exhaustive_patterns
181- || cx. tcx . features ( ) . min_exhaustive_patterns )
182- && cx. is_uninhabited ( ty) ;
183-
184- let skip = is_uninhabited && ( !is_visible || is_non_exhaustive) ;
185- let ty = cx. reveal_opaque_ty ( ty) ;
186- ( FieldIdx :: new ( i) , ty, skip)
171+ let ty = self . tcx . normalize_erasing_regions ( self . param_env , ty) ;
172+ let ty = self . reveal_opaque_ty ( ty) ;
173+ ( field, ty)
187174 } )
188175 }
189176
@@ -230,9 +217,21 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
230217 } else {
231218 let variant =
232219 & adt. variant ( RustcMatchCheckCtxt :: variant_index_for_adt ( & ctor, * adt) ) ;
233- let tys = cx
234- . list_variant_nonhidden_fields ( ty, variant)
235- . map ( |( _, ty, skip) | ( ty, SkipField ( skip) ) ) ;
220+
221+ // In the cases of either a `#[non_exhaustive]` field list or a non-public
222+ // field, we skip uninhabited fields in order not to reveal the
223+ // uninhabitedness of the whole variant.
224+ let is_non_exhaustive =
225+ variant. is_field_list_non_exhaustive ( ) && !adt. did ( ) . is_local ( ) ;
226+ let tys = cx. variant_sub_tys ( ty, variant) . map ( |( field, ty) | {
227+ let is_visible =
228+ adt. is_enum ( ) || field. vis . is_accessible_from ( cx. module , cx. tcx ) ;
229+ let is_uninhabited = ( cx. tcx . features ( ) . exhaustive_patterns
230+ || cx. tcx . features ( ) . min_exhaustive_patterns )
231+ && cx. is_uninhabited ( * ty) ;
232+ let skip = is_uninhabited && ( !is_visible || is_non_exhaustive) ;
233+ ( ty, SkipField ( skip) )
234+ } ) ;
236235 cx. dropless_arena . alloc_from_iter ( tys)
237236 }
238237 }
@@ -269,9 +268,8 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
269268 // patterns. If we're here we can assume this is a box pattern.
270269 1
271270 } else {
272- let variant =
273- & adt. variant ( RustcMatchCheckCtxt :: variant_index_for_adt ( & ctor, * adt) ) ;
274- self . list_variant_nonhidden_fields ( ty, variant) . count ( )
271+ let variant_idx = RustcMatchCheckCtxt :: variant_index_for_adt ( & ctor, * adt) ;
272+ adt. variant ( variant_idx) . fields . len ( )
275273 }
276274 }
277275 _ => bug ! ( "Unexpected type for constructor `{ctor:?}`: {ty:?}" ) ,
@@ -507,20 +505,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
507505 } ;
508506 let variant =
509507 & adt. variant ( RustcMatchCheckCtxt :: variant_index_for_adt ( & ctor, * adt) ) ;
510- // For each field in the variant, we store the relevant index into `self.fields` if any.
511- let mut field_id_to_id: Vec < Option < usize > > =
512- ( 0 ..variant. fields . len ( ) ) . map ( |_| None ) . collect ( ) ;
513- let tys = cx. list_variant_nonhidden_fields ( ty, variant) . enumerate ( ) . map (
514- |( i, ( field, ty, _) ) | {
515- field_id_to_id[ field. index ( ) ] = Some ( i) ;
516- ty
517- } ,
518- ) ;
519- fields = tys. map ( |ty| DeconstructedPat :: wildcard ( ty) ) . collect ( ) ;
508+ fields = cx
509+ . variant_sub_tys ( ty, variant)
510+ . map ( |( _, ty) | DeconstructedPat :: wildcard ( ty) )
511+ . collect ( ) ;
520512 for pat in subpatterns {
521- if let Some ( i) = field_id_to_id[ pat. field . index ( ) ] {
522- fields[ i] = self . lower_pat ( & pat. pattern ) ;
523- }
513+ fields[ pat. field . index ( ) ] = self . lower_pat ( & pat. pattern ) ;
524514 }
525515 }
526516 _ => bug ! ( "pattern has unexpected type: pat: {:?}, ty: {:?}" , pat, ty) ,
@@ -762,11 +752,9 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
762752 ty:: Adt ( adt_def, args) => {
763753 let variant_index =
764754 RustcMatchCheckCtxt :: variant_index_for_adt ( & pat. ctor ( ) , * adt_def) ;
765- let variant = & adt_def. variant ( variant_index) ;
766- let subpatterns = cx
767- . list_variant_nonhidden_fields ( * pat. ty ( ) , variant)
768- . zip ( subpatterns)
769- . map ( |( ( field, _ty, _) , pattern) | FieldPat { field, pattern } )
755+ let subpatterns = subpatterns
756+ . enumerate ( )
757+ . map ( |( i, pattern) | FieldPat { field : FieldIdx :: new ( i) , pattern } )
770758 . collect ( ) ;
771759
772760 if adt_def. is_enum ( ) {
0 commit comments