From 983f6b97872d4dc2b7aaf2f9b088d433904e2f0e Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 21 Jun 2023 02:22:55 +0000
Subject: [PATCH 1/3] Normalize opaques with escaping bound vars

---
 compiler/rustc_trait_selection/src/traits/project.rs       | 6 +-----
 .../rustc_trait_selection/src/traits/query/normalize.rs    | 7 +------
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index c84c75cecdf..8440cbdecad 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -500,10 +500,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
         // to make sure we don't forget to fold the substs regardless.
 
         match kind {
-            // 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 if !data.substs.has_escaping_bound_vars() => {
+            ty::Opaque => {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.super_fold_with(self),
@@ -529,7 +526,6 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                     }
                 }
             }
-            ty::Opaque => ty.super_fold_with(self),
 
             ty::Projection if !data.has_escaping_bound_vars() => {
                 // This branch is *mostly* just an optimization: when we don't
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 1b6e92946c4..edad519cec2 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -211,10 +211,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
 
         // Wrap this in a closure so we don't accidentally return from the outer function
         let res = match kind {
-            // 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 if !data.substs.has_escaping_bound_vars() => {
+            ty::Opaque => {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.try_super_fold_with(self)?,
@@ -255,8 +252,6 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                 }
             }
 
-            ty::Opaque => ty.try_super_fold_with(self)?,
-
             ty::Projection | ty::Inherent | ty::Weak => {
                 // See note in `rustc_trait_selection::traits::project`
 

From 75a8f681837c70051e0200a14f58ae07dbe58e66 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Fri, 23 Jun 2023 21:50:44 +0000
Subject: [PATCH 2/3] Remove unnecessary DefineOpaqueTypes::Bubble from codegen

---
 compiler/rustc_traits/src/codegen.rs | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 5f84acc8a04..ef50fa23caf 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -5,7 +5,7 @@
 
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
-use rustc_middle::traits::{CodegenObligationError, DefiningAnchor};
+use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::{
@@ -29,13 +29,7 @@ pub fn codegen_select_candidate<'tcx>(
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    let infcx = tcx
-        .infer_ctxt()
-        .ignoring_regions()
-        .with_opaque_type_inference(DefiningAnchor::Bubble)
-        .build();
-    //~^ HACK `Bubble` is required for
-    // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
+    let infcx = tcx.infer_ctxt().ignoring_regions().build();
     let mut selcx = SelectionContext::new(&infcx);
 
     let obligation_cause = ObligationCause::dummy();
@@ -79,10 +73,5 @@ pub fn codegen_select_candidate<'tcx>(
     let impl_source = infcx.resolve_vars_if_possible(impl_source);
     let impl_source = infcx.tcx.erase_regions(impl_source);
 
-    // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
-    // as they will get constrained elsewhere, too.
-    // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
-    let _ = infcx.take_opaque_types();
-
     Ok(&*tcx.arena.alloc(impl_source))
 }

From bfc6ca8207a0fda58a89ee7a9d2d109efdce5ab1 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Fri, 23 Jun 2023 22:00:55 +0000
Subject: [PATCH 3/3] More tests

---
 .../normalize-opaque-with-bound-vars.rs       | 64 +++++++++++++++++++
 .../normalize-opaque-with-bound-vars.rs       | 27 ++++++++
 2 files changed, 91 insertions(+)
 create mode 100644 tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs
 create mode 100644 tests/ui/impl-trait/normalize-opaque-with-bound-vars.rs

diff --git a/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs
new file mode 100644
index 00000000000..c4008f2b7e7
--- /dev/null
+++ b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs
@@ -0,0 +1,64 @@
+// build-pass
+// edition:2021
+// compile-flags: -Cdebuginfo=2
+
+// We were not normalizing opaques with escaping bound vars during codegen,
+// leading to later errors during debuginfo computation.
+
+#![feature(async_fn_in_trait)]
+
+#[derive(Clone, Copy)]
+pub struct SharedState {}
+
+pub trait State {
+    async fn execute(self, shared_state: &SharedState);
+}
+
+pub trait StateComposer {
+    fn and_then<T, F>(self, map_fn: F) -> AndThen<Self, F>
+    where
+        Self: State + Sized,
+        T: State,
+        F: FnOnce() -> T,
+    {
+        AndThen { previous: self, map_fn }
+    }
+}
+
+impl<T> StateComposer for T where T: State {}
+pub struct AndThen<T, F> {
+    previous: T,
+    map_fn: F,
+}
+
+impl<T, U, F> State for AndThen<T, F>
+where
+    T: State,
+    U: State,
+    F: FnOnce() -> U,
+{
+    async fn execute(self, shared_state: &SharedState)
+    where
+        Self: Sized,
+    {
+        self.previous.execute(shared_state).await;
+        (self.map_fn)().execute(shared_state).await
+    }
+}
+
+pub struct SomeState {}
+
+impl State for SomeState {
+    async fn execute(self, shared_state: &SharedState) {}
+}
+
+pub fn main() {
+    let shared_state = SharedState {};
+    async {
+        SomeState {}
+            .and_then(|| SomeState {})
+            .and_then(|| SomeState {})
+            .execute(&shared_state)
+            .await;
+    };
+}
diff --git a/tests/ui/impl-trait/normalize-opaque-with-bound-vars.rs b/tests/ui/impl-trait/normalize-opaque-with-bound-vars.rs
new file mode 100644
index 00000000000..1025c2c7e8a
--- /dev/null
+++ b/tests/ui/impl-trait/normalize-opaque-with-bound-vars.rs
@@ -0,0 +1,27 @@
+// build-pass
+// edition:2021
+// compile-flags: -Cdebuginfo=2
+
+// We were not normalizing opaques with escaping bound vars during codegen,
+// leading to later linker errors because of differences in mangled symbol name.
+
+fn func<T>() -> impl Sized {}
+
+trait Trait<'a> {
+    type Assoc;
+
+    fn call() {
+        let _ = async {
+            let _value = func::<Self::Assoc>();
+            std::future::ready(()).await
+        };
+    }
+}
+
+impl Trait<'static> for () {
+    type Assoc = ();
+}
+
+fn main() {
+    <()>::call();
+}