From 7f11d6f4bf8c4574b29d683ff72e596e7bcfbb50 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 29 May 2024 14:06:39 -0400
Subject: [PATCH 1/3] Add lang items for AsyncFn's associated types

---
 compiler/rustc_hir/src/lang_items.rs          |  3 +++
 compiler/rustc_span/src/symbol.rs             |  3 +++
 .../src/solve/normalizes_to/mod.rs            | 22 ++++++++++++-------
 library/core/src/ops/async_function.rs        |  3 +++
 4 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index c4be67cdd88..410c2ed8703 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -228,6 +228,9 @@ language_item_table! {
     AsyncFn,                 sym::async_fn,            async_fn_trait,             Target::Trait,          GenericRequirement::Exact(1);
     AsyncFnMut,              sym::async_fn_mut,        async_fn_mut_trait,         Target::Trait,          GenericRequirement::Exact(1);
     AsyncFnOnce,             sym::async_fn_once,       async_fn_once_trait,        Target::Trait,          GenericRequirement::Exact(1);
+    AsyncFnOnceOutput,       sym::async_fn_once_output,async_fn_once_output,       Target::AssocTy,        GenericRequirement::Exact(1);
+    CallOnceFuture,          sym::call_once_future,    call_once_future,           Target::AssocTy,        GenericRequirement::Exact(1);
+    CallRefFuture,           sym::call_ref_future,     call_ref_future,            Target::AssocTy,        GenericRequirement::Exact(2);
     AsyncFnKindHelper,       sym::async_fn_kind_helper,async_fn_kind_helper,       Target::Trait,          GenericRequirement::Exact(1);
 
     FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy,        GenericRequirement::None;
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 90da220b3f5..cabd462cc8a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -441,6 +441,7 @@ symbols! {
         async_fn_kind_helper,
         async_fn_mut,
         async_fn_once,
+        async_fn_once_output,
         async_fn_track_caller,
         async_fn_traits,
         async_for_loop,
@@ -498,6 +499,8 @@ symbols! {
         call,
         call_mut,
         call_once,
+        call_once_future,
+        call_ref_future,
         caller_location,
         capture_disjoint_fields,
         catch_unwind,
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index 7fd2a3801cc..f9e164e1f3f 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -407,16 +407,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                      output_coroutine_ty,
                      coroutine_return_ty,
                  }| {
-                    let (projection_term, term) = match tcx.item_name(goal.predicate.def_id()) {
-                        sym::CallOnceFuture => (
+                    let lang_items = tcx.lang_items();
+                    let (projection_term, term) = if Some(goal.predicate.def_id())
+                        == lang_items.call_once_future()
+                    {
+                        (
                             ty::AliasTerm::new(
                                 tcx,
                                 goal.predicate.def_id(),
                                 [goal.predicate.self_ty(), tupled_inputs_ty],
                             ),
                             output_coroutine_ty.into(),
-                        ),
-                        sym::CallRefFuture => (
+                        )
+                    } else if Some(goal.predicate.def_id()) == lang_items.call_ref_future() {
+                        (
                             ty::AliasTerm::new(
                                 tcx,
                                 goal.predicate.def_id(),
@@ -427,8 +431,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                                 ],
                             ),
                             output_coroutine_ty.into(),
-                        ),
-                        sym::Output => (
+                        )
+                    } else if Some(goal.predicate.def_id()) == lang_items.async_fn_once_output() {
+                        (
                             ty::AliasTerm::new(
                                 tcx,
                                 goal.predicate.def_id(),
@@ -438,8 +443,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                                 ],
                             ),
                             coroutine_return_ty.into(),
-                        ),
-                        name => bug!("no such associated type: {name}"),
+                        )
+                    } else {
+                        bug!("no such associated type in `AsyncFn*`: {:?}", goal.predicate.def_id())
                     };
                     ty::ProjectionPredicate { projection_term, term }
                 },
diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs
index 18bcee5a1c7..fc21ffd5246 100644
--- a/library/core/src/ops/async_function.rs
+++ b/library/core/src/ops/async_function.rs
@@ -26,6 +26,7 @@ pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> {
 pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
     /// Future returned by [`AsyncFnMut::async_call_mut`] and [`AsyncFn::async_call`].
     #[unstable(feature = "async_fn_traits", issue = "none")]
+    #[cfg_attr(not(bootstrap), lang = "call_ref_future")]
     type CallRefFuture<'a>: Future<Output = Self::Output>
     where
         Self: 'a;
@@ -46,10 +47,12 @@ pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
 pub trait AsyncFnOnce<Args: Tuple> {
     /// Future returned by [`AsyncFnOnce::async_call_once`].
     #[unstable(feature = "async_fn_traits", issue = "none")]
+    #[cfg_attr(not(bootstrap), lang = "call_once_future")]
     type CallOnceFuture: Future<Output = Self::Output>;
 
     /// Output type of the called closure's future.
     #[unstable(feature = "async_fn_traits", issue = "none")]
+    #[cfg_attr(not(bootstrap), lang = "async_fn_once_output")]
     type Output;
 
     /// Call the [`AsyncFnOnce`], returning a future which may move out of the called closure.

From a9c7e024c08ce4c7172cf3a46d0d16222eb4991f Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 29 May 2024 14:22:56 -0400
Subject: [PATCH 2/3] Add lang item for Future::Output

---
 compiler/rustc_hir/src/lang_items.rs             |  1 +
 compiler/rustc_hir_analysis/src/collect.rs       |  2 +-
 compiler/rustc_span/src/symbol.rs                |  2 +-
 .../src/solve/assembly/structural_traits.rs      | 14 ++------------
 .../rustc_trait_selection/src/traits/project.rs  | 16 ++--------------
 library/core/src/future/future.rs                |  2 +-
 6 files changed, 8 insertions(+), 29 deletions(-)

diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 410c2ed8703..67114a6212c 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -238,6 +238,7 @@ language_item_table! {
     Iterator,                sym::iterator,            iterator_trait,             Target::Trait,          GenericRequirement::Exact(0);
     FusedIterator,           sym::fused_iterator,      fused_iterator_trait,       Target::Trait,          GenericRequirement::Exact(0);
     Future,                  sym::future_trait,        future_trait,               Target::Trait,          GenericRequirement::Exact(0);
+    FutureOutput,            sym::future_output,       future_output,              Target::AssocTy,        GenericRequirement::Exact(0);
     AsyncIterator,           sym::async_iterator,      async_iterator_trait,       Target::Trait,          GenericRequirement::Exact(0);
 
     CoroutineState,          sym::coroutine_state,     coroutine_state,            Target::Enum,           GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 75e35e7bf50..7e746006148 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1478,7 +1478,7 @@ pub fn suggest_impl_trait<'tcx>(
         ),
         (
             infcx.tcx.lang_items().future_trait(),
-            infcx.tcx.get_diagnostic_item(sym::FutureOutput),
+            infcx.tcx.lang_items().future_output(),
             format_as_assoc,
         ),
         (
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index cabd462cc8a..fa4ef923cc0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -210,7 +210,6 @@ symbols! {
         FsPermissions,
         FusedIterator,
         Future,
-        FutureOutput,
         GlobalAlloc,
         Hash,
         HashMap,
@@ -914,6 +913,7 @@ symbols! {
         fundamental,
         fused_iterator,
         future,
+        future_output,
         future_trait,
         gdb_script_file,
         ge,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 64d5f725a1f..67cf0c3b2fd 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -454,12 +454,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                     .rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]))
                     .upcast(tcx),
             ];
-            let future_output_def_id = tcx
-                .associated_items(future_trait_def_id)
-                .filter_by_name_unhygienic(sym::Output)
-                .next()
-                .unwrap()
-                .def_id;
+            let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
             let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
             Ok((
                 bound_sig.rebind(AsyncCallableRelevantTypes {
@@ -510,12 +505,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                 );
             }
 
-            let future_output_def_id = tcx
-                .associated_items(future_trait_def_id)
-                .filter_by_name_unhygienic(sym::Output)
-                .next()
-                .unwrap()
-                .def_id;
+            let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
             let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
             Ok((
                 bound_sig.rebind(AsyncCallableRelevantTypes {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 87c8b1cda50..c92c8369fed 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1880,13 +1880,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
             let term = match item_name {
                 sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
                 sym::Output => {
-                    let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
-                    let future_output_def_id = tcx
-                        .associated_items(future_trait_def_id)
-                        .filter_by_name_unhygienic(sym::Output)
-                        .next()
-                        .unwrap()
-                        .def_id;
+                    let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
                     Ty::new_projection(tcx, future_output_def_id, [sig.output()])
                 }
                 name => bug!("no such associated type: {name}"),
@@ -1919,13 +1913,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
             let term = match item_name {
                 sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
                 sym::Output => {
-                    let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
-                    let future_output_def_id = tcx
-                        .associated_items(future_trait_def_id)
-                        .filter_by_name_unhygienic(sym::Output)
-                        .next()
-                        .unwrap()
-                        .def_id;
+                    let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
                     Ty::new_projection(tcx, future_output_def_id, [sig.output()])
                 }
                 name => bug!("no such associated type: {name}"),
diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs
index f965afc8a59..86963b548b9 100644
--- a/library/core/src/future/future.rs
+++ b/library/core/src/future/future.rs
@@ -35,7 +35,7 @@ use crate::task::{Context, Poll};
 pub trait Future {
     /// The type of value produced on completion.
     #[stable(feature = "futures_api", since = "1.36.0")]
-    #[rustc_diagnostic_item = "FutureOutput"]
+    #[cfg_attr(not(bootstrap), lang = "future_output")]
     type Output;
 
     /// Attempt to resolve the future to a final value, registering

From a03ba7fd2d0a94bd29f1ed7618c6e7ceecd3222c Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 29 May 2024 14:28:53 -0400
Subject: [PATCH 3/3] Add lang item for AsyncFnKindHelper::Upvars

---
 compiler/rustc_hir/src/lang_items.rs          |  5 +++--
 compiler/rustc_span/src/symbol.rs             |  1 +
 .../src/solve/assembly/structural_traits.rs   |  9 +--------
 .../src/traits/project.rs                     | 20 ++++---------------
 library/core/src/ops/async_function.rs        |  1 +
 5 files changed, 10 insertions(+), 26 deletions(-)

diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 67114a6212c..f5f7bae11b2 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -228,10 +228,11 @@ language_item_table! {
     AsyncFn,                 sym::async_fn,            async_fn_trait,             Target::Trait,          GenericRequirement::Exact(1);
     AsyncFnMut,              sym::async_fn_mut,        async_fn_mut_trait,         Target::Trait,          GenericRequirement::Exact(1);
     AsyncFnOnce,             sym::async_fn_once,       async_fn_once_trait,        Target::Trait,          GenericRequirement::Exact(1);
-    AsyncFnOnceOutput,       sym::async_fn_once_output,async_fn_once_output,       Target::AssocTy,        GenericRequirement::Exact(1);
+    AsyncFnOnceOutput,       sym::async_fn_once_output, async_fn_once_output,       Target::AssocTy,        GenericRequirement::Exact(1);
     CallOnceFuture,          sym::call_once_future,    call_once_future,           Target::AssocTy,        GenericRequirement::Exact(1);
     CallRefFuture,           sym::call_ref_future,     call_ref_future,            Target::AssocTy,        GenericRequirement::Exact(2);
-    AsyncFnKindHelper,       sym::async_fn_kind_helper,async_fn_kind_helper,       Target::Trait,          GenericRequirement::Exact(1);
+    AsyncFnKindHelper,       sym::async_fn_kind_helper, async_fn_kind_helper,      Target::Trait,          GenericRequirement::Exact(1);
+    AsyncFnKindUpvars,       sym::async_fn_kind_upvars, async_fn_kind_upvars,      Target::AssocTy,          GenericRequirement::Exact(5);
 
     FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy,        GenericRequirement::None;
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index fa4ef923cc0..25ecb9a31c6 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -438,6 +438,7 @@ symbols! {
         async_fn,
         async_fn_in_trait,
         async_fn_kind_helper,
+        async_fn_kind_upvars,
         async_fn_mut,
         async_fn_once,
         async_fn_once_output,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 67cf0c3b2fd..08796ef3109 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -9,7 +9,6 @@ use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::bug;
 use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, Upcast};
-use rustc_span::sym;
 
 use crate::solve::EvalCtxt;
 
@@ -582,13 +581,7 @@ fn coroutine_closure_to_ambiguous_coroutine<'tcx>(
     args: ty::CoroutineClosureArgs<'tcx>,
     sig: ty::CoroutineClosureSignature<'tcx>,
 ) -> Ty<'tcx> {
-    let async_fn_kind_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
-    let upvars_projection_def_id = tcx
-        .associated_items(async_fn_kind_trait_def_id)
-        .filter_by_name_unhygienic(sym::Upvars)
-        .next()
-        .unwrap()
-        .def_id;
+    let upvars_projection_def_id = tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
     let tupled_upvars_ty = Ty::new_projection(
         tcx,
         upvars_projection_def_id,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index c92c8369fed..b6557e6c4eb 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1680,14 +1680,8 @@ fn confirm_closure_candidate<'cx, 'tcx>(
                         args.coroutine_captures_by_ref_ty(),
                     )
                 } else {
-                    let async_fn_kind_trait_def_id =
-                        tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
-                    let upvars_projection_def_id = tcx
-                        .associated_items(async_fn_kind_trait_def_id)
-                        .filter_by_name_unhygienic(sym::Upvars)
-                        .next()
-                        .unwrap()
-                        .def_id;
+                    let upvars_projection_def_id =
+                        tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
                     let tupled_upvars_ty = Ty::new_projection(
                         tcx,
                         upvars_projection_def_id,
@@ -1816,14 +1810,8 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                             args.coroutine_captures_by_ref_ty(),
                         )
                     } else {
-                        let async_fn_kind_trait_def_id =
-                            tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
-                        let upvars_projection_def_id = tcx
-                            .associated_items(async_fn_kind_trait_def_id)
-                            .filter_by_name_unhygienic(sym::Upvars)
-                            .next()
-                            .unwrap()
-                            .def_id;
+                        let upvars_projection_def_id =
+                            tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
                         // When we don't know the closure kind (and therefore also the closure's upvars,
                         // which are computed at the same time), we must delay the computation of the
                         // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs
index fc21ffd5246..f4e9d1a63ac 100644
--- a/library/core/src/ops/async_function.rs
+++ b/library/core/src/ops/async_function.rs
@@ -146,6 +146,7 @@ mod internal_implementation_detail {
         // `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder
         // of the closure's self-capture, and these upvar types will be instantiated with
         // the `'closure_env` region provided to the associated type.
+        #[cfg_attr(not(bootstrap), lang = "async_fn_kind_upvars")]
         type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
     }
 }