@@ -319,7 +319,9 @@ use rustc_arena::TypedArena;
319319use rustc_data_structures:: stack:: ensure_sufficient_stack;
320320use rustc_hir:: def_id:: DefId ;
321321use 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+ } ;
323325use rustc_session:: lint;
324326use rustc_session:: lint:: builtin:: NON_EXHAUSTIVE_OMITTED_PATTERNS ;
325327use rustc_span:: { Span , DUMMY_SP } ;
@@ -363,17 +365,40 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
363365
364366 /// Type inference occasionally gives us opaque types in places where corresponding patterns
365367 /// 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.
367370 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+ }
373388 }
389+
390+ if ty. has_opaque_types ( ) { ty. super_fold_with ( self ) } else { ty }
374391 }
375392 }
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+ }
377402 }
378403}
379404
0 commit comments