@@ -10,15 +10,15 @@ 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 } ;
1717
1818use crate :: constructor:: {
1919 IntRange , MaybeInfiniteInt , OpaqueId , RangeEnd , Slice , SliceKind , VariantVisibility ,
2020} ;
21- use crate :: { errors, Captures , TypeCx } ;
21+ use crate :: { errors, Captures , PrivateUninhabitedField , TypeCx } ;
2222
2323use crate :: constructor:: Constructor :: * ;
2424
@@ -158,34 +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 > ) > + 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) ;
176170 // `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)
189174 } )
190175 }
191176
@@ -210,12 +195,17 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
210195 & ' a self ,
211196 ctor : & ' a Constructor < ' p , ' tcx > ,
212197 ty : RevealedTy < ' tcx > ,
213- ) -> impl Iterator < Item = RevealedTy < ' tcx > > + ExactSizeIterator + Captures < ' a > {
198+ ) -> impl Iterator < Item = ( RevealedTy < ' tcx > , PrivateUninhabitedField ) >
199+ + ExactSizeIterator
200+ + Captures < ' a > {
214201 fn reveal_and_alloc < ' a , ' tcx > (
215202 cx : & ' a RustcMatchCheckCtxt < ' _ , ' tcx > ,
216203 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+ )
219209 }
220210 let cx = self ;
221211 let slice = match ctor {
@@ -229,7 +219,21 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
229219 } else {
230220 let variant =
231221 & 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+ } ) ;
233237 cx. dropless_arena . alloc_from_iter ( tys)
234238 }
235239 }
@@ -246,16 +250,8 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
246250 }
247251 _ => bug ! ( "bad slice pattern {:?} {:?}" , ctor, ty) ,
248252 } ,
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 => & [ ] ,
259255 Or => {
260256 bug ! ( "called `Fields::wildcards` on an `Or` ctor" )
261257 }
@@ -274,25 +270,16 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
274270 // patterns. If we're here we can assume this is a box pattern.
275271 1
276272 } 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 ( )
280275 }
281276 }
282277 _ => bug ! ( "Unexpected type for constructor `{ctor:?}`: {ty:?}" ) ,
283278 } ,
284279 Ref => 1 ,
285280 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 ,
296283 Or => bug ! ( "The `Or` constructor doesn't have a fixed arity" ) ,
297284 }
298285 }
@@ -520,20 +507,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
520507 } ;
521508 let variant =
522509 & 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 ( ) ;
533514 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 ) ;
537516 }
538517 }
539518 _ => bug ! ( "pattern has unexpected type: pat: {:?}, ty: {:?}" , pat, ty) ,
@@ -775,11 +754,9 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
775754 ty:: Adt ( adt_def, args) => {
776755 let variant_index =
777756 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 } )
783760 . collect ( ) ;
784761
785762 if adt_def. is_enum ( ) {
@@ -830,7 +807,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
830807 }
831808 }
832809 & Str ( value) => PatKind :: Constant { value } ,
833- Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
810+ Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind :: Wild ,
834811 Missing { .. } => bug ! (
835812 "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
836813 `Missing` should have been processed in `apply_constructors`"
@@ -866,7 +843,8 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
866843 & ' a self ,
867844 ctor : & ' a crate :: constructor:: Constructor < Self > ,
868845 ty : & ' a Self :: Ty ,
869- ) -> impl Iterator < Item = Self :: Ty > + ExactSizeIterator + Captures < ' a > {
846+ ) -> impl Iterator < Item = ( Self :: Ty , PrivateUninhabitedField ) > + ExactSizeIterator + Captures < ' a >
847+ {
870848 self . ctor_sub_tys ( ctor, * ty)
871849 }
872850 fn ctors_for_ty (
0 commit comments