@@ -318,7 +318,9 @@ use rustc_arena::TypedArena;
318
318
use rustc_data_structures:: stack:: ensure_sufficient_stack;
319
319
use rustc_hir:: def_id:: DefId ;
320
320
use rustc_hir:: HirId ;
321
- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
321
+ use rustc_middle:: ty:: {
322
+ self , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitableExt ,
323
+ } ;
322
324
use rustc_session:: lint;
323
325
use rustc_session:: lint:: builtin:: NON_EXHAUSTIVE_OMITTED_PATTERNS ;
324
326
use rustc_span:: { Span , DUMMY_SP } ;
@@ -362,17 +364,40 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
362
364
363
365
/// Type inference occasionally gives us opaque types in places where corresponding patterns
364
366
/// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited
365
- /// types, we use the corresponding concrete type if possible.
367
+ /// types, we use the corresponding concrete type if possible. This recursively reveals all the
368
+ /// opaque types in `ty` that we can.
366
369
fn reveal_opaque_ty ( & self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
367
- if let ty:: Alias ( ty:: Opaque , alias_ty) = ty. kind ( ) {
368
- if let Some ( local_def_id) = alias_ty. def_id . as_local ( ) {
369
- let key = ty:: OpaqueTypeKey { def_id : local_def_id, args : alias_ty. args } ;
370
- if let Some ( real_ty) = self . typeck_results . concrete_opaque_types . get ( & key) {
371
- return real_ty. ty ;
370
+ struct RevealOpaqueTys < ' tcx > {
371
+ tcx : TyCtxt < ' tcx > ,
372
+ typeck_results : & ' tcx ty:: TypeckResults < ' tcx > ,
373
+ }
374
+
375
+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for RevealOpaqueTys < ' tcx > {
376
+ fn interner ( & self ) -> TyCtxt < ' tcx > {
377
+ self . tcx
378
+ }
379
+ fn fold_ty ( & mut self , mut ty : Ty < ' tcx > ) -> Ty < ' tcx > {
380
+ if let ty:: Alias ( ty:: Opaque , alias_ty) = ty. kind ( ) {
381
+ if let Some ( local_def_id) = alias_ty. def_id . as_local ( ) {
382
+ let key = ty:: OpaqueTypeKey { def_id : local_def_id, args : alias_ty. args } ;
383
+ if let Some ( real_ty) = self . typeck_results . concrete_opaque_types . get ( & key) {
384
+ ty = real_ty. ty ;
385
+ }
386
+ }
372
387
}
388
+
389
+ if ty. has_opaque_types ( ) { ty. super_fold_with ( self ) } else { ty }
373
390
}
374
391
}
375
- ty
392
+
393
+ if ty. has_opaque_types ( ) {
394
+ ty. fold_with ( & mut RevealOpaqueTys {
395
+ tcx : self . tcx ,
396
+ typeck_results : self . typeck_results ,
397
+ } )
398
+ } else {
399
+ ty
400
+ }
376
401
}
377
402
}
378
403
0 commit comments