Rollup merge of #65293 - tmandry:turbo-expander, r=matthewjasper

Optimize `try_expand_impl_trait_type`

A lot of time was being spent expanding some large `impl Future` types in fuchsia. This PR takes the number of types being visited in one expansion from >3 billion to about a thousand, and eliminates the compile time regression in https://github.com/rust-lang/rust/issues/65147 (in fact, compile times are better than they were before).

Thanks to @Mark-Simulacrum for helping identify the issue and to @matthewjasper for suggesting this change.

Fixes #65147.
r? @matthewjasper,@nikomatsakis
This commit is contained in:
Tyler Mandry 2019-10-15 16:07:47 -07:00 committed by GitHub
commit a6ae7ae63f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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<DefId>,
// 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<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
primary_def_id: DefId,
found_recursion: bool,
tcx: TyCtxt<'tcx>,
@ -713,9 +716,16 @@ 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);
let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
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.expanded_cache.insert((def_id, substs), expanded_ty);
expanded_ty
}
};
self.seen_opaque_tys.remove(&def_id);
Some(expanded_ty)
} else {
@ -735,14 +745,17 @@ impl<'tcx> TyCtxt<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Opaque(def_id, substs) = t.kind {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
} else {
} else if t.has_projections() {
t.super_fold_with(self)
} else {
t
}
}
}
let mut visitor = OpaqueTypeExpander {
seen_opaque_tys: FxHashSet::default(),
expanded_cache: FxHashMap::default(),
primary_def_id: def_id,
found_recursion: false,
tcx: self,