diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index d0e95a18c59fc..131a4ed312731 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -697,6 +697,9 @@ impl<'tcx> TyCtxt<'tcx> { // that type, and when we finish expanding that type we remove the // its DefId. seen_opaque_tys: FxHashSet, + // Cache of all expansions we've seen so far. This is a critical + // optimization for some large types produced by async fn trees. + expanded_cache: FxHashMap>, primary_def_id: DefId, found_recursion: bool, tcx: TyCtxt<'tcx>, @@ -713,10 +716,17 @@ impl<'tcx> TyCtxt<'tcx> { } let substs = substs.fold_with(self); if self.seen_opaque_tys.insert(def_id) { - let generic_ty = self.tcx.type_of(def_id); - let concrete_ty = generic_ty.subst(self.tcx, substs); - let expanded_ty = self.fold_ty(concrete_ty); - self.seen_opaque_tys.remove(&def_id); + let expanded_ty = match self.expanded_cache.get(&def_id) { + Some(expanded_ty) => expanded_ty, + None => { + let generic_ty = self.tcx.type_of(def_id); + let concrete_ty = generic_ty.subst(self.tcx, substs); + let expanded_ty = self.fold_ty(concrete_ty); + self.seen_opaque_tys.remove(&def_id); + self.expanded_cache.insert(def_id, expanded_ty); + expanded_ty + } + }; Some(expanded_ty) } else { // If another opaque type that we contain is recursive, then it @@ -743,6 +753,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), + expanded_cache: FxHashMap::default(), primary_def_id: def_id, found_recursion: false, tcx: self, diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr index 7572c6c1bf057..bd16c2cf72730 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr @@ -20,7 +20,7 @@ error[E0720]: opaque type expands to a recursive type LL | fn recursive_wrap() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `((impl Sized,),)` + = note: expanded type is `(impl Sized,)` error[E0720]: opaque type expands to a recursive type --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:21:25 @@ -28,7 +28,7 @@ error[E0720]: opaque type expands to a recursive type LL | fn recursive_wrap2() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `((impl Sized,),)` + = note: expanded type is `(impl Sized,)` error: aborting due to 4 previous errors