Auto merge of #68772 - matthewjasper:relate-opt, r=davidtwco

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
This commit is contained in:
bors 2020-02-03 06:38:34 +00:00
commit 0d34a87722
3 changed files with 42 additions and 2 deletions

View File

@ -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());
}
}
}

View File

@ -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() {
@ -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

View File

@ -0,0 +1,23 @@
// Check that this can be compiled in a reasonable time.
// build-pass
fn main() {
// 96 nested closures
let x = ();
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
|| || || || || || || ||
[&(), &x];
}