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