@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
88use rustc_pattern_analysis:: {
99 constructor:: { Constructor , ConstructorSet , VariantVisibility } ,
1010 index:: IdxContainer ,
11- Captures , TypeCx ,
11+ Captures , PrivateUninhabitedField , TypeCx ,
1212} ;
1313use smallvec:: { smallvec, SmallVec } ;
1414use stdx:: never;
@@ -88,39 +88,21 @@ impl<'p> MatchCheckCtx<'p> {
8888 }
8989 }
9090
91- // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
92- // uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
93- // This lists the fields we keep along with their types.
94- fn list_variant_nonhidden_fields < ' a > (
91+ // This lists the fields of a variant along with their types.
92+ fn list_variant_fields < ' a > (
9593 & ' a self ,
9694 ty : & ' a Ty ,
9795 variant : VariantId ,
9896 ) -> impl Iterator < Item = ( LocalFieldId , Ty ) > + Captures < ' a > + Captures < ' p > {
99- let cx = self ;
100- let ( adt, substs) = ty. as_adt ( ) . unwrap ( ) ;
101-
102- let adt_is_local = variant. module ( cx. db . upcast ( ) ) . krate ( ) == cx. module . krate ( ) ;
103-
104- // Whether we must not match the fields of this variant exhaustively.
105- let is_non_exhaustive =
106- cx. db . attrs ( variant. into ( ) ) . by_key ( "non_exhaustive" ) . exists ( ) && !adt_is_local;
97+ let ( _, substs) = ty. as_adt ( ) . unwrap ( ) ;
10798
108- let visibility = cx. db . field_visibilities ( variant) ;
109- let field_ty = cx. db . field_types ( variant) ;
110- let fields_len = variant. variant_data ( cx. db . upcast ( ) ) . fields ( ) . len ( ) as u32 ;
99+ let field_tys = self . db . field_types ( variant) ;
100+ let fields_len = variant. variant_data ( self . db . upcast ( ) ) . fields ( ) . len ( ) as u32 ;
111101
112- ( 0 ..fields_len) . map ( |idx| LocalFieldId :: from_raw ( idx. into ( ) ) ) . filter_map ( move |fid| {
113- let ty = field_ty[ fid] . clone ( ) . substitute ( Interner , substs) ;
114- let ty = normalize ( cx. db , cx. db . trait_environment_for_body ( cx. body ) , ty) ;
115- let is_visible = matches ! ( adt, hir_def:: AdtId :: EnumId ( ..) )
116- || visibility[ fid] . is_visible_from ( cx. db . upcast ( ) , cx. module ) ;
117- let is_uninhabited = cx. is_uninhabited ( & ty) ;
118-
119- if is_uninhabited && ( !is_visible || is_non_exhaustive) {
120- None
121- } else {
122- Some ( ( fid, ty) )
123- }
102+ ( 0 ..fields_len) . map ( |idx| LocalFieldId :: from_raw ( idx. into ( ) ) ) . map ( move |fid| {
103+ let ty = field_tys[ fid] . clone ( ) . substitute ( Interner , substs) ;
104+ let ty = normalize ( self . db , self . db . trait_environment_for_body ( self . body ) , ty) ;
105+ ( fid, ty)
124106 } )
125107 }
126108
@@ -199,23 +181,16 @@ impl<'p> MatchCheckCtx<'p> {
199181 }
200182 } ;
201183 let variant = Self :: variant_id_for_adt ( & ctor, adt. 0 ) . unwrap ( ) ;
202- let fields_len = variant. variant_data ( self . db . upcast ( ) ) . fields ( ) . len ( ) ;
203- // For each field in the variant, we store the relevant index into `self.fields` if any.
204- let mut field_id_to_id: Vec < Option < usize > > = vec ! [ None ; fields_len] ;
205- let tys = self
206- . list_variant_nonhidden_fields ( & pat. ty , variant)
207- . enumerate ( )
208- . map ( |( i, ( fid, ty) ) | {
209- let field_idx: u32 = fid. into_raw ( ) . into ( ) ;
210- field_id_to_id[ field_idx as usize ] = Some ( i) ;
211- ty
212- } ) ;
213- let mut wilds: Vec < _ > = tys. map ( DeconstructedPat :: wildcard) . collect ( ) ;
184+ // Fill a vec with wildcards, then place the fields we have at the right
185+ // index.
186+ let mut wilds: Vec < _ > = self
187+ . list_variant_fields ( & pat. ty , variant)
188+ . map ( |( _, ty) | ty)
189+ . map ( DeconstructedPat :: wildcard)
190+ . collect ( ) ;
214191 for pat in subpatterns {
215- let field_idx: u32 = pat. field . into_raw ( ) . into ( ) ;
216- if let Some ( i) = field_id_to_id[ field_idx as usize ] {
217- wilds[ i] = self . lower_pat ( & pat. pattern ) ;
218- }
192+ let field_id: u32 = pat. field . into_raw ( ) . into ( ) ;
193+ wilds[ field_id as usize ] = self . lower_pat ( & pat. pattern ) ;
219194 }
220195 fields = wilds;
221196 }
@@ -263,7 +238,7 @@ impl<'p> MatchCheckCtx<'p> {
263238 TyKind :: Adt ( adt, substs) => {
264239 let variant = Self :: variant_id_for_adt ( pat. ctor ( ) , adt. 0 ) . unwrap ( ) ;
265240 let subpatterns = self
266- . list_variant_nonhidden_fields ( pat. ty ( ) , variant)
241+ . list_variant_fields ( pat. ty ( ) , variant)
267242 . zip ( subpatterns)
268243 . map ( |( ( field, _ty) , pattern) | FieldPat { field, pattern } )
269244 . collect ( ) ;
@@ -286,7 +261,7 @@ impl<'p> MatchCheckCtx<'p> {
286261 Ref => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
287262 Slice ( _) => unimplemented ! ( ) ,
288263 & Str ( void) => match void { } ,
289- Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
264+ Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind :: Wild ,
290265 Missing | F32Range ( ..) | F64Range ( ..) | Opaque ( ..) | Or => {
291266 never ! ( "can't convert to pattern: {:?}" , pat. ctor( ) ) ;
292267 PatKind :: Wild
@@ -326,7 +301,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
326301 1
327302 } else {
328303 let variant = Self :: variant_id_for_adt ( ctor, adt) . unwrap ( ) ;
329- self . list_variant_nonhidden_fields ( ty , variant ) . count ( )
304+ variant . variant_data ( self . db . upcast ( ) ) . fields ( ) . len ( )
330305 }
331306 }
332307 _ => {
@@ -337,7 +312,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
337312 Ref => 1 ,
338313 Slice ( ..) => unimplemented ! ( ) ,
339314 Bool ( ..) | IntRange ( ..) | F32Range ( ..) | F64Range ( ..) | Str ( ..) | Opaque ( ..)
340- | NonExhaustive | Hidden | Missing | Wildcard => 0 ,
315+ | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => 0 ,
341316 Or => {
342317 never ! ( "The `Or` constructor doesn't have a fixed arity" ) ;
343318 0
@@ -349,13 +324,13 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
349324 & ' a self ,
350325 ctor : & ' a rustc_pattern_analysis:: constructor:: Constructor < Self > ,
351326 ty : & ' a Self :: Ty ,
352- ) -> impl ExactSizeIterator < Item = Self :: Ty > + Captures < ' a > {
353- let single = |ty| smallvec ! [ ty ] ;
327+ ) -> impl ExactSizeIterator < Item = ( Self :: Ty , PrivateUninhabitedField ) > + Captures < ' a > {
328+ let single = |ty| smallvec ! [ ( ty , PrivateUninhabitedField ( false ) ) ] ;
354329 let tys: SmallVec < [ _ ; 2 ] > = match ctor {
355330 Struct | Variant ( _) | UnionField => match ty. kind ( Interner ) {
356331 TyKind :: Tuple ( _, substs) => {
357332 let tys = substs. iter ( Interner ) . map ( |ty| ty. assert_ty_ref ( Interner ) ) ;
358- tys. cloned ( ) . collect ( )
333+ tys. cloned ( ) . map ( |ty| ( ty , PrivateUninhabitedField ( false ) ) ) . collect ( )
359334 }
360335 TyKind :: Ref ( .., rty) => single ( rty. clone ( ) ) ,
361336 & TyKind :: Adt ( AdtId ( adt) , ref substs) => {
@@ -366,7 +341,27 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
366341 single ( subst_ty)
367342 } else {
368343 let variant = Self :: variant_id_for_adt ( ctor, adt) . unwrap ( ) ;
369- self . list_variant_nonhidden_fields ( ty, variant) . map ( |( _, ty) | ty) . collect ( )
344+ let ( adt, _) = ty. as_adt ( ) . unwrap ( ) ;
345+
346+ let adt_is_local =
347+ variant. module ( self . db . upcast ( ) ) . krate ( ) == self . module . krate ( ) ;
348+ // Whether we must not match the fields of this variant exhaustively.
349+ let is_non_exhaustive =
350+ self . db . attrs ( variant. into ( ) ) . by_key ( "non_exhaustive" ) . exists ( )
351+ && !adt_is_local;
352+ let visibilities = self . db . field_visibilities ( variant) ;
353+
354+ self . list_variant_fields ( ty, variant)
355+ . map ( move |( fid, ty) | {
356+ let is_visible = matches ! ( adt, hir_def:: AdtId :: EnumId ( ..) )
357+ || visibilities[ fid]
358+ . is_visible_from ( self . db . upcast ( ) , self . module ) ;
359+ let is_uninhabited = self . is_uninhabited ( & ty) ;
360+ let private_uninhabited =
361+ is_uninhabited && ( !is_visible || is_non_exhaustive) ;
362+ ( ty, PrivateUninhabitedField ( private_uninhabited) )
363+ } )
364+ . collect ( )
370365 }
371366 }
372367 ty_kind => {
@@ -383,7 +378,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
383378 } ,
384379 Slice ( _) => unreachable ! ( "Found a `Slice` constructor in match checking" ) ,
385380 Bool ( ..) | IntRange ( ..) | F32Range ( ..) | F64Range ( ..) | Str ( ..) | Opaque ( ..)
386- | NonExhaustive | Hidden | Missing | Wildcard => smallvec ! [ ] ,
381+ | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => smallvec ! [ ] ,
387382 Or => {
388383 never ! ( "called `Fields::wildcards` on an `Or` ctor" ) ;
389384 smallvec ! [ ]
@@ -478,6 +473,11 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
478473 fn bug ( & self , fmt : fmt:: Arguments < ' _ > ) {
479474 debug ! ( "{}" , fmt)
480475 }
476+
477+ fn complexity_exceeded ( & self ) -> Result < ( ) , Self :: Error > {
478+ // FIXME(Nadrieril): make use of the complexity counter.
479+ Err ( ( ) )
480+ }
481481}
482482
483483impl < ' p > fmt:: Debug for MatchCheckCtx < ' p > {
0 commit comments