@@ -10,7 +10,7 @@ use rustc_middle::mir::interpret::Scalar;
10
10
use rustc_middle:: mir:: { self , Const } ;
11
11
use rustc_middle:: thir:: { FieldPat , Pat , PatKind , PatRange , PatRangeBoundary } ;
12
12
use 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 } ;
14
14
use rustc_session:: lint;
15
15
use rustc_span:: { ErrorGuaranteed , Span , DUMMY_SP } ;
16
16
use rustc_target:: abi:: { FieldIdx , Integer , VariantIdx , FIRST_VARIANT } ;
@@ -158,32 +158,19 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
158
158
}
159
159
}
160
160
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 (
165
162
& self ,
166
163
ty : RevealedTy < ' tcx > ,
167
164
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 < ' _ >
169
166
{
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) ;
177
170
// `field.ty()` doesn't normalize after instantiating.
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)
187
174
} )
188
175
}
189
176
@@ -230,9 +217,21 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
230
217
} else {
231
218
let variant =
232
219
& 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
+ } ) ;
236
235
cx. dropless_arena . alloc_from_iter ( tys)
237
236
}
238
237
}
@@ -269,9 +268,8 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
269
268
// patterns. If we're here we can assume this is a box pattern.
270
269
1
271
270
} 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 ( )
275
273
}
276
274
}
277
275
_ => bug ! ( "Unexpected type for constructor `{ctor:?}`: {ty:?}" ) ,
@@ -507,20 +505,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
507
505
} ;
508
506
let variant =
509
507
& 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 ( ) ;
520
512
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 ) ;
524
514
}
525
515
}
526
516
_ => bug ! ( "pattern has unexpected type: pat: {:?}, ty: {:?}" , pat, ty) ,
@@ -762,11 +752,9 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
762
752
ty:: Adt ( adt_def, args) => {
763
753
let variant_index =
764
754
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 } )
770
758
. collect ( ) ;
771
759
772
760
if adt_def. is_enum ( ) {
0 commit comments