@@ -697,6 +697,9 @@ impl<'tcx> TyCtxt<'tcx> {
697697 // that type, and when we finish expanding that type we remove the
698698 // its DefId.
699699 seen_opaque_tys : FxHashSet < DefId > ,
700+ // Cache of all expansions we've seen so far. This is a critical
701+ // optimization for some large types produced by async fn trees.
702+ expanded_cache : FxHashMap < DefId , Ty < ' tcx > > ,
700703 primary_def_id : DefId ,
701704 found_recursion : bool ,
702705 tcx : TyCtxt < ' tcx > ,
@@ -713,10 +716,17 @@ impl<'tcx> TyCtxt<'tcx> {
713716 }
714717 let substs = substs. fold_with ( self ) ;
715718 if self . seen_opaque_tys . insert ( def_id) {
716- let generic_ty = self . tcx . type_of ( def_id) ;
717- let concrete_ty = generic_ty. subst ( self . tcx , substs) ;
718- let expanded_ty = self . fold_ty ( concrete_ty) ;
719- self . seen_opaque_tys . remove ( & def_id) ;
719+ let expanded_ty = match self . expanded_cache . get ( & def_id) {
720+ Some ( expanded_ty) => expanded_ty,
721+ None => {
722+ let generic_ty = self . tcx . type_of ( def_id) ;
723+ let concrete_ty = generic_ty. subst ( self . tcx , substs) ;
724+ let expanded_ty = self . fold_ty ( concrete_ty) ;
725+ self . seen_opaque_tys . remove ( & def_id) ;
726+ self . expanded_cache . insert ( def_id, expanded_ty) ;
727+ expanded_ty
728+ }
729+ } ;
720730 Some ( expanded_ty)
721731 } else {
722732 // If another opaque type that we contain is recursive, then it
@@ -743,6 +753,7 @@ impl<'tcx> TyCtxt<'tcx> {
743753
744754 let mut visitor = OpaqueTypeExpander {
745755 seen_opaque_tys : FxHashSet :: default ( ) ,
756+ expanded_cache : FxHashMap :: default ( ) ,
746757 primary_def_id : def_id,
747758 found_recursion : false ,
748759 tcx : self ,
0 commit comments