@@ -318,7 +318,9 @@ use rustc_arena::TypedArena;
318318use rustc_data_structures:: stack:: ensure_sufficient_stack;
319319use rustc_hir:: def_id:: DefId ;
320320use 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+ } ;
322324use rustc_session:: lint;
323325use rustc_session:: lint:: builtin:: NON_EXHAUSTIVE_OMITTED_PATTERNS ;
324326use rustc_span:: { Span , DUMMY_SP } ;
@@ -362,17 +364,40 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
362364
363365 /// Type inference occasionally gives us opaque types in places where corresponding patterns
364366 /// 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.
366369 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+ }
372387 }
388+
389+ if ty. has_opaque_types ( ) { ty. super_fold_with ( self ) } else { ty }
373390 }
374391 }
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+ }
376401 }
377402}
378403
0 commit comments