@@ -10,15 +10,15 @@ 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 } ;
17
17
18
18
use crate :: constructor:: {
19
19
IntRange , MaybeInfiniteInt , OpaqueId , RangeEnd , Slice , SliceKind , VariantVisibility ,
20
20
} ;
21
- use crate :: { errors, Captures , TypeCx } ;
21
+ use crate :: { errors, Captures , PrivateUninhabitedField , TypeCx } ;
22
22
23
23
use crate :: constructor:: Constructor :: * ;
24
24
@@ -158,34 +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 > ) > + Captures < ' p > + Captures < ' _ > {
169
- let cx = self ;
170
- let ty:: Adt ( adt, args) = ty. kind ( ) else { bug ! ( ) } ;
171
- // Whether we must not match the fields of this variant exhaustively.
172
- let is_non_exhaustive = variant. is_field_list_non_exhaustive ( ) && !adt. did ( ) . is_local ( ) ;
173
-
174
- variant. fields . iter ( ) . enumerate ( ) . filter_map ( move |( i, field) | {
175
- let ty = field. ty ( cx. tcx , args) ;
165
+ ) -> impl Iterator < Item = ( & ' tcx FieldDef , RevealedTy < ' tcx > ) > + Captures < ' p > + Captures < ' _ >
166
+ {
167
+ let ty:: Adt ( _, args) = ty. kind ( ) else { bug ! ( ) } ;
168
+ variant. fields . iter ( ) . map ( move |field| {
169
+ let ty = field. ty ( self . tcx , args) ;
176
170
// `field.ty()` doesn't normalize after instantiating.
177
- let ty = cx. tcx . normalize_erasing_regions ( cx. param_env , ty) ;
178
- let is_visible = adt. is_enum ( ) || field. vis . is_accessible_from ( cx. module , cx. tcx ) ;
179
- let is_uninhabited = ( cx. tcx . features ( ) . exhaustive_patterns
180
- || cx. tcx . features ( ) . min_exhaustive_patterns )
181
- && cx. is_uninhabited ( ty) ;
182
-
183
- if is_uninhabited && ( !is_visible || is_non_exhaustive) {
184
- None
185
- } else {
186
- let ty = cx. reveal_opaque_ty ( ty) ;
187
- Some ( ( FieldIdx :: new ( i) , ty) )
188
- }
171
+ let ty = self . tcx . normalize_erasing_regions ( self . param_env , ty) ;
172
+ let ty = self . reveal_opaque_ty ( ty) ;
173
+ ( field, ty)
189
174
} )
190
175
}
191
176
@@ -210,12 +195,17 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
210
195
& ' a self ,
211
196
ctor : & ' a Constructor < ' p , ' tcx > ,
212
197
ty : RevealedTy < ' tcx > ,
213
- ) -> impl Iterator < Item = RevealedTy < ' tcx > > + ExactSizeIterator + Captures < ' a > {
198
+ ) -> impl Iterator < Item = ( RevealedTy < ' tcx > , PrivateUninhabitedField ) >
199
+ + ExactSizeIterator
200
+ + Captures < ' a > {
214
201
fn reveal_and_alloc < ' a , ' tcx > (
215
202
cx : & ' a RustcMatchCheckCtxt < ' _ , ' tcx > ,
216
203
iter : impl Iterator < Item = Ty < ' tcx > > ,
217
- ) -> & ' a [ RevealedTy < ' tcx > ] {
218
- cx. dropless_arena . alloc_from_iter ( iter. map ( |ty| cx. reveal_opaque_ty ( ty) ) )
204
+ ) -> & ' a [ ( RevealedTy < ' tcx > , PrivateUninhabitedField ) ] {
205
+ cx. dropless_arena . alloc_from_iter (
206
+ iter. map ( |ty| cx. reveal_opaque_ty ( ty) )
207
+ . map ( |ty| ( ty, PrivateUninhabitedField ( false ) ) ) ,
208
+ )
219
209
}
220
210
let cx = self ;
221
211
let slice = match ctor {
@@ -229,7 +219,21 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
229
219
} else {
230
220
let variant =
231
221
& adt. variant ( RustcMatchCheckCtxt :: variant_index_for_adt ( & ctor, * adt) ) ;
232
- let tys = cx. list_variant_nonhidden_fields ( ty, variant) . map ( |( _, ty) | ty) ;
222
+
223
+ // In the cases of either a `#[non_exhaustive]` field list or a non-public
224
+ // field, we skip uninhabited fields in order not to reveal the
225
+ // uninhabitedness of the whole variant.
226
+ let is_non_exhaustive =
227
+ variant. is_field_list_non_exhaustive ( ) && !adt. did ( ) . is_local ( ) ;
228
+ let tys = cx. variant_sub_tys ( ty, variant) . map ( |( field, ty) | {
229
+ let is_visible =
230
+ adt. is_enum ( ) || field. vis . is_accessible_from ( cx. module , cx. tcx ) ;
231
+ let is_uninhabited = ( cx. tcx . features ( ) . exhaustive_patterns
232
+ || cx. tcx . features ( ) . min_exhaustive_patterns )
233
+ && cx. is_uninhabited ( * ty) ;
234
+ let skip = is_uninhabited && ( !is_visible || is_non_exhaustive) ;
235
+ ( ty, PrivateUninhabitedField ( skip) )
236
+ } ) ;
233
237
cx. dropless_arena . alloc_from_iter ( tys)
234
238
}
235
239
}
@@ -246,16 +250,8 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
246
250
}
247
251
_ => bug ! ( "bad slice pattern {:?} {:?}" , ctor, ty) ,
248
252
} ,
249
- Bool ( ..)
250
- | IntRange ( ..)
251
- | F32Range ( ..)
252
- | F64Range ( ..)
253
- | Str ( ..)
254
- | Opaque ( ..)
255
- | NonExhaustive
256
- | Hidden
257
- | Missing { .. }
258
- | Wildcard => & [ ] ,
253
+ Bool ( ..) | IntRange ( ..) | F32Range ( ..) | F64Range ( ..) | Str ( ..) | Opaque ( ..)
254
+ | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => & [ ] ,
259
255
Or => {
260
256
bug ! ( "called `Fields::wildcards` on an `Or` ctor" )
261
257
}
@@ -274,25 +270,16 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
274
270
// patterns. If we're here we can assume this is a box pattern.
275
271
1
276
272
} else {
277
- let variant =
278
- & adt. variant ( RustcMatchCheckCtxt :: variant_index_for_adt ( & ctor, * adt) ) ;
279
- self . list_variant_nonhidden_fields ( ty, variant) . count ( )
273
+ let variant_idx = RustcMatchCheckCtxt :: variant_index_for_adt ( & ctor, * adt) ;
274
+ adt. variant ( variant_idx) . fields . len ( )
280
275
}
281
276
}
282
277
_ => bug ! ( "Unexpected type for constructor `{ctor:?}`: {ty:?}" ) ,
283
278
} ,
284
279
Ref => 1 ,
285
280
Slice ( slice) => slice. arity ( ) ,
286
- Bool ( ..)
287
- | IntRange ( ..)
288
- | F32Range ( ..)
289
- | F64Range ( ..)
290
- | Str ( ..)
291
- | Opaque ( ..)
292
- | NonExhaustive
293
- | Hidden
294
- | Missing { .. }
295
- | Wildcard => 0 ,
281
+ Bool ( ..) | IntRange ( ..) | F32Range ( ..) | F64Range ( ..) | Str ( ..) | Opaque ( ..)
282
+ | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => 0 ,
296
283
Or => bug ! ( "The `Or` constructor doesn't have a fixed arity" ) ,
297
284
}
298
285
}
@@ -520,20 +507,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
520
507
} ;
521
508
let variant =
522
509
& adt. variant ( RustcMatchCheckCtxt :: variant_index_for_adt ( & ctor, * adt) ) ;
523
- // For each field in the variant, we store the relevant index into `self.fields` if any.
524
- let mut field_id_to_id: Vec < Option < usize > > =
525
- ( 0 ..variant. fields . len ( ) ) . map ( |_| None ) . collect ( ) ;
526
- let tys = cx. list_variant_nonhidden_fields ( ty, variant) . enumerate ( ) . map (
527
- |( i, ( field, ty) ) | {
528
- field_id_to_id[ field. index ( ) ] = Some ( i) ;
529
- ty
530
- } ,
531
- ) ;
532
- fields = tys. map ( |ty| DeconstructedPat :: wildcard ( ty) ) . collect ( ) ;
510
+ fields = cx
511
+ . variant_sub_tys ( ty, variant)
512
+ . map ( |( _, ty) | DeconstructedPat :: wildcard ( ty) )
513
+ . collect ( ) ;
533
514
for pat in subpatterns {
534
- if let Some ( i) = field_id_to_id[ pat. field . index ( ) ] {
535
- fields[ i] = self . lower_pat ( & pat. pattern ) ;
536
- }
515
+ fields[ pat. field . index ( ) ] = self . lower_pat ( & pat. pattern ) ;
537
516
}
538
517
}
539
518
_ => bug ! ( "pattern has unexpected type: pat: {:?}, ty: {:?}" , pat, ty) ,
@@ -775,11 +754,9 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
775
754
ty:: Adt ( adt_def, args) => {
776
755
let variant_index =
777
756
RustcMatchCheckCtxt :: variant_index_for_adt ( & pat. ctor ( ) , * adt_def) ;
778
- let variant = & adt_def. variant ( variant_index) ;
779
- let subpatterns = cx
780
- . list_variant_nonhidden_fields ( * pat. ty ( ) , variant)
781
- . zip ( subpatterns)
782
- . map ( |( ( field, _ty) , pattern) | FieldPat { field, pattern } )
757
+ let subpatterns = subpatterns
758
+ . enumerate ( )
759
+ . map ( |( i, pattern) | FieldPat { field : FieldIdx :: new ( i) , pattern } )
783
760
. collect ( ) ;
784
761
785
762
if adt_def. is_enum ( ) {
@@ -830,7 +807,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
830
807
}
831
808
}
832
809
& Str ( value) => PatKind :: Constant { value } ,
833
- Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
810
+ Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind :: Wild ,
834
811
Missing { .. } => bug ! (
835
812
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
836
813
`Missing` should have been processed in `apply_constructors`"
@@ -866,7 +843,8 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
866
843
& ' a self ,
867
844
ctor : & ' a crate :: constructor:: Constructor < Self > ,
868
845
ty : & ' a Self :: Ty ,
869
- ) -> impl Iterator < Item = Self :: Ty > + ExactSizeIterator + Captures < ' a > {
846
+ ) -> impl Iterator < Item = ( Self :: Ty , PrivateUninhabitedField ) > + ExactSizeIterator + Captures < ' a >
847
+ {
870
848
self . ctor_sub_tys ( ctor, * ty)
871
849
}
872
850
fn ctors_for_ty (
0 commit comments