about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-09-27 14:08:13 +0000
committerbors <bors@rust-lang.org>2021-09-27 14:08:13 +0000
commit2b6ed3b675475abc01ce7e68bb75b457f0c85684 (patch)
treee17c038639d97f818bf2d3d19696d929320aa1e8
parent3e8f32e1c52ca493c862facb7a69e7c3f1f97a18 (diff)
parenta84e3fab307f562312c54991e3c7386246ba3f75 (diff)
downloadrust-2b6ed3b675475abc01ce7e68bb75b457f0c85684.tar.gz
rust-2b6ed3b675475abc01ce7e68bb75b457f0c85684.zip
Auto merge of #89285 - jackh726:issue-88862, r=nikomatsakis
Don't normalize opaque types with escaping late-bound regions

Fixes #88862

Turns out, this has some really bad perf implications in large types (issue #88862). While we technically can handle them fine, it doesn't change test output either way. For now, revert with an added benchmark. Future attempts to change this back will have to consider perf.

Needs a perf run once https://github.com/rust-lang/rustc-perf/pull/1033 is merged

r? `@nikomatsakis`
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs8
2 files changed, 8 insertions, 8 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index baf6b725648..47b006985ec 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -388,15 +388,15 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
         // to make sure we don't forget to fold the substs regardless.
 
         match *ty.kind() {
-            ty::Opaque(def_id, substs) => {
+            // This is really important. While we *can* handle this, this has
+            // severe performance implications for large opaque types with
+            // late-bound regions. See `issue-88862` benchmark.
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.super_fold_with(self),
 
                     Reveal::All => {
-                        // N.b. there is an assumption here all this code can handle
-                        // escaping bound vars.
-
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
                             let obligation = Obligation::with_depth(
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index ed5fe466c69..1364cf1c995 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -206,15 +206,15 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
 
         // Wrap this in a closure so we don't accidentally return from the outer function
         let res = (|| match *ty.kind() {
-            ty::Opaque(def_id, substs) => {
+            // This is really important. While we *can* handle this, this has
+            // severe performance implications for large opaque types with
+            // late-bound regions. See `issue-88862` benchmark.
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.super_fold_with(self),
 
                     Reveal::All => {
-                        // N.b. there is an assumption here all this code can handle
-                        // escaping bound vars.
-
                         let substs = substs.super_fold_with(self);
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {