@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
8
8
use rustc_pattern_analysis:: {
9
9
constructor:: { Constructor , ConstructorSet , VariantVisibility } ,
10
10
index:: IdxContainer ,
11
- Captures , TypeCx ,
11
+ Captures , PrivateUninhabitedField , TypeCx ,
12
12
} ;
13
13
use smallvec:: { smallvec, SmallVec } ;
14
14
use stdx:: never;
@@ -88,39 +88,21 @@ impl<'p> MatchCheckCtx<'p> {
88
88
}
89
89
}
90
90
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 > (
95
93
& ' a self ,
96
94
ty : & ' a Ty ,
97
95
variant : VariantId ,
98
96
) -> 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 ( ) ;
107
98
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 ;
111
101
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)
124
106
} )
125
107
}
126
108
@@ -199,23 +181,16 @@ impl<'p> MatchCheckCtx<'p> {
199
181
}
200
182
} ;
201
183
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 ( ) ;
214
191
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 ) ;
219
194
}
220
195
fields = wilds;
221
196
}
@@ -263,7 +238,7 @@ impl<'p> MatchCheckCtx<'p> {
263
238
TyKind :: Adt ( adt, substs) => {
264
239
let variant = Self :: variant_id_for_adt ( pat. ctor ( ) , adt. 0 ) . unwrap ( ) ;
265
240
let subpatterns = self
266
- . list_variant_nonhidden_fields ( pat. ty ( ) , variant)
241
+ . list_variant_fields ( pat. ty ( ) , variant)
267
242
. zip ( subpatterns)
268
243
. map ( |( ( field, _ty) , pattern) | FieldPat { field, pattern } )
269
244
. collect ( ) ;
@@ -286,7 +261,7 @@ impl<'p> MatchCheckCtx<'p> {
286
261
Ref => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
287
262
Slice ( _) => unimplemented ! ( ) ,
288
263
& Str ( void) => match void { } ,
289
- Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
264
+ Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind :: Wild ,
290
265
Missing | F32Range ( ..) | F64Range ( ..) | Opaque ( ..) | Or => {
291
266
never ! ( "can't convert to pattern: {:?}" , pat. ctor( ) ) ;
292
267
PatKind :: Wild
@@ -326,7 +301,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
326
301
1
327
302
} else {
328
303
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 ( )
330
305
}
331
306
}
332
307
_ => {
@@ -337,7 +312,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
337
312
Ref => 1 ,
338
313
Slice ( ..) => unimplemented ! ( ) ,
339
314
Bool ( ..) | IntRange ( ..) | F32Range ( ..) | F64Range ( ..) | Str ( ..) | Opaque ( ..)
340
- | NonExhaustive | Hidden | Missing | Wildcard => 0 ,
315
+ | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => 0 ,
341
316
Or => {
342
317
never ! ( "The `Or` constructor doesn't have a fixed arity" ) ;
343
318
0
@@ -349,13 +324,13 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
349
324
& ' a self ,
350
325
ctor : & ' a rustc_pattern_analysis:: constructor:: Constructor < Self > ,
351
326
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 ) ) ] ;
354
329
let tys: SmallVec < [ _ ; 2 ] > = match ctor {
355
330
Struct | Variant ( _) | UnionField => match ty. kind ( Interner ) {
356
331
TyKind :: Tuple ( _, substs) => {
357
332
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 ( )
359
334
}
360
335
TyKind :: Ref ( .., rty) => single ( rty. clone ( ) ) ,
361
336
& TyKind :: Adt ( AdtId ( adt) , ref substs) => {
@@ -366,7 +341,27 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
366
341
single ( subst_ty)
367
342
} else {
368
343
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 ( )
370
365
}
371
366
}
372
367
ty_kind => {
@@ -383,7 +378,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
383
378
} ,
384
379
Slice ( _) => unreachable ! ( "Found a `Slice` constructor in match checking" ) ,
385
380
Bool ( ..) | IntRange ( ..) | F32Range ( ..) | F64Range ( ..) | Str ( ..) | Opaque ( ..)
386
- | NonExhaustive | Hidden | Missing | Wildcard => smallvec ! [ ] ,
381
+ | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => smallvec ! [ ] ,
387
382
Or => {
388
383
never ! ( "called `Fields::wildcards` on an `Or` ctor" ) ;
389
384
smallvec ! [ ]
@@ -478,6 +473,11 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
478
473
fn bug ( & self , fmt : fmt:: Arguments < ' _ > ) {
479
474
debug ! ( "{}" , fmt)
480
475
}
476
+
477
+ fn complexity_exceeded ( & self ) -> Result < ( ) , Self :: Error > {
478
+ // FIXME(Nadrieril): make use of the complexity counter.
479
+ Err ( ( ) )
480
+ }
481
481
}
482
482
483
483
impl < ' p > fmt:: Debug for MatchCheckCtx < ' p > {
0 commit comments