Skip to content

Commit

Permalink
Auto merge of #68772 - matthewjasper:relate-opt, r=davidtwco
Browse files Browse the repository at this point in the history
Avoid exponential behaviour when relating types

When equating bound types we check subtyping in both directions. Since closures are invariant in their substs, we end up comparing the two types an exponential number of times. If there are no bound variables this isn't needed.

Closes #68061
  • Loading branch information
bors committed Feb 3, 2020
2 parents a2e8030 + a606ffd commit 0d34a87
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/librustc/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,13 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
where
T: Relate<'tcx>,
{
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
self.fields.higher_ranked_sub(b, a, self.a_is_expected)
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
self.fields.higher_ranked_sub(b, a, self.a_is_expected)
} else {
// Fast path for the common case.
self.relate(a.skip_binder(), b.skip_binder())?;
return Ok(a.clone());
}
}
}
11 changes: 11 additions & 0 deletions src/librustc/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,10 @@ where
b = self.infcx.shallow_resolve(b);
}

if a == b {
return Ok(a);
}

match (&a.kind, &b.kind) {
(_, &ty::Infer(ty::TyVar(vid))) => {
if D::forbid_inference_vars() {
Expand Down Expand Up @@ -638,6 +642,13 @@ where

debug!("binders({:?}: {:?}, ambient_variance={:?})", a, b, self.ambient_variance);

if !a.skip_binder().has_escaping_bound_vars() && !b.skip_binder().has_escaping_bound_vars()
{
// Fast path for the common case.
self.relate(a.skip_binder(), b.skip_binder())?;
return Ok(a.clone());
}

if self.ambient_covariance() {
// Covariance, so we want `for<..> A <: for<..> B` --
// therefore we compare any instantiation of A (i.e., A
Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/closures/deeply-nested_closures.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Check that this can be compiled in a reasonable time.

// build-pass

fn main() {
// 96 nested closures
let x = ();
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||

|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||

|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
[&(), &x];
}

0 comments on commit 0d34a87

Please sign in to comment.