about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-01-25 03:50:23 +0000
committerMichael Goulet <michael@errs.io>2024-02-06 02:22:58 +0000
commit881b6b5149e882434a8df80a829bcfde0a2e9d37 (patch)
treea929ae3c67bf3df264beb0407bccd2e28b2f1a64
parent427896dd7e39f1aaf3e3cbc15e5ddf77d45a6aec (diff)
downloadrust-881b6b5149e882434a8df80a829bcfde0a2e9d37.tar.gz
rust-881b6b5149e882434a8df80a829bcfde0a2e9d37.zip
Bless tests, add comments
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs5
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs12
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/traits/select.rs4
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs5
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs36
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs14
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs6
-rw-r--r--library/core/src/ops/async_function.rs21
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-closure-error.rs3
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-closure-error.stderr28
-rw-r--r--tests/ui/async-await/async-closures/higher-ranked.rs4
-rw-r--r--tests/ui/async-await/async-closures/higher-ranked.stderr17
-rw-r--r--tests/ui/async-await/issue-74072-lifetime-name-annotations.rs6
-rw-r--r--tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr90
-rw-r--r--tests/ui/closures/binder/async-closure-with-binder.rs7
-rw-r--r--tests/ui/closures/binder/async-closure-with-binder.stderr16
-rw-r--r--tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr12
-rw-r--r--tests/ui/symbol-names/basic.legacy.stderr4
-rw-r--r--tests/ui/symbol-names/issue-60925.legacy.stderr4
28 files changed, 201 insertions, 126 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index ace9c5ae71d..46fd0ce2b39 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -47,8 +47,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             user_provided_sig,
         );
 
-        // FIXME(async_closures): We must apply the same transformation to our
-        // signature here as we do during closure checking.
+        // FIXME(async_closures): It's kind of wacky that we must apply this
+        // transformation here, since we do the same thing in HIR typeck.
+        // Maybe we could just fix up the canonicalized signature during HIR typeck?
         if let DefiningTy::CoroutineClosure(_, args) =
             self.borrowck_context.universal_regions.defining_ty
         {
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 9c266d123b3..d696e624823 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -98,7 +98,10 @@ pub enum DefiningTy<'tcx> {
     Coroutine(DefId, GenericArgsRef<'tcx>),
 
     /// The MIR is a special kind of closure that returns coroutines.
-    /// TODO: describe how to make the sig...
+    ///
+    /// See the documentation on `CoroutineClosureSignature` for details
+    /// on how to construct the callable signature of the coroutine from
+    /// its args.
     CoroutineClosure(DefId, GenericArgsRef<'tcx>),
 
     /// The MIR is a fn item with the given `DefId` and args. The signature
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index d30c7a4fb38..23fb7eba656 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -335,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     continue;
                 }
 
-                // For this check, we do *not* want to treat async coroutine closures (async blocks)
+                // For this check, we do *not* want to treat async coroutine-closures (async blocks)
                 // as proper closures. Doing so would regress type inference when feeding
                 // the return value of an argument-position async block to an argument-position
                 // closure wrapped in a block.
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index d88e9261e5a..3d6c28088ad 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -262,8 +262,16 @@ pub struct CoroutineInfo<'tcx> {
     /// Coroutine drop glue. This field is populated after the state transform pass.
     pub coroutine_drop: Option<Body<'tcx>>,
 
-    /// The body of the coroutine, modified to take its upvars by move.
-    /// TODO:
+    /// The body of the coroutine, modified to take its upvars by move rather than by ref.
+    ///
+    /// This is used by coroutine-closures, which must return a different flavor of coroutine
+    /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` which
+    /// is run right after building the initial MIR, and will only be populated for coroutines
+    /// which come out of the async closure desugaring.
+    ///
+    /// This body should be processed in lockstep with the containing body -- any optimization
+    /// passes, etc, should be applied to this body as well. This is done automatically if
+    /// using `run_passes`.
     pub by_move_body: Option<Body<'tcx>>,
 
     /// The layout of a coroutine. This field is populated after the state transform pass.
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f9ab32b16f5..938fba0ed09 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -756,7 +756,7 @@ rustc_queries! {
     }
 
     query coroutine_for_closure(def_id: DefId) -> DefId {
-        desc { |_tcx| "TODO" }
+        desc { |_tcx| "Given a coroutine-closure def id, return the def id of the coroutine returned by it" }
         separate_provide_extern
     }
 
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 4e11575cf98..28eba133c76 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -138,7 +138,9 @@ pub enum SelectionCandidate<'tcx> {
     /// generated for an `async ||` expression.
     AsyncClosureCandidate,
 
-    // TODO:
+    /// Implementation of the the `AsyncFnKindHelper` helper trait, which
+    /// is used internally to delay computation for async closures until after
+    /// upvar analysis is performed in HIR typeck.
     AsyncFnKindHelperCandidate,
 
     /// Implementation of a `Coroutine` trait by one of the anonymous types
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 44bf3c32b48..2c80dd02145 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -101,7 +101,10 @@ pub enum InstanceDef<'tcx> {
         target_kind: ty::ClosureKind,
     },
 
-    /// TODO:
+    /// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce`
+    /// is called on a coroutine-closure whose closure kind is not `FnOnce`. This
+    /// will select the body that is produced by the `ByMoveBody` transform, and thus
+    /// take and use all of its upvars by-move rather than by-ref.
     CoroutineByMoveShim { coroutine_def_id: DefId },
 
     /// Compiler-generated accessor for thread locals which returns a reference to the thread local
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index be6b887ba7d..c0bfd2380ad 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -877,7 +877,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::CoroutineClosure(did, args) => {
                 p!(write("{{"));
                 if !self.should_print_verbose() {
-                    p!(write("coroutine closure"));
+                    p!(write("coroutine-closure"));
                     // FIXME(eddyb) should use `def_span`.
                     if let Some(did) = did.as_local() {
                         if self.tcx().sess.opts.unstable_opts.span_free_formats {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 8918a3735d6..3bbebaddbdd 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -276,11 +276,31 @@ pub struct CoroutineClosureArgs<'tcx> {
 }
 
 pub struct CoroutineClosureArgsParts<'tcx> {
+    /// This is the args of the typeck root.
     pub parent_args: &'tcx [GenericArg<'tcx>],
+    /// Represents the maximum calling capability of the closure.
     pub closure_kind_ty: Ty<'tcx>,
+    /// Represents all of the relevant parts of the coroutine returned by this
+    /// coroutine-closure. This signature parts type will have the general
+    /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where
+    /// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the
+    /// coroutine returned by the coroutine-closure.
+    ///
+    /// Use `coroutine_closure_sig` to break up this type rather than using it
+    /// yourself.
     pub signature_parts_ty: Ty<'tcx>,
+    /// The upvars captured by the closure. Remains an inference variable
+    /// until the upvar analysis, which happens late in HIR typeck.
     pub tupled_upvars_ty: Ty<'tcx>,
+    /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`.
+    /// This allows us to represent the binder of the self-captures of the closure.
+    ///
+    /// For example, if the coroutine returned by the closure borrows `String`
+    /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`,
+    /// while the `tupled_upvars_ty`, representing the by-move version of the same
+    /// captures, will be `(String,)`.
     pub coroutine_captures_by_ref_ty: Ty<'tcx>,
+    /// Witness type returned by the generator produced by this coroutine-closure.
     pub coroutine_witness_ty: Ty<'tcx>,
 }
 
@@ -496,15 +516,27 @@ pub struct CoroutineArgs<'tcx> {
 pub struct CoroutineArgsParts<'tcx> {
     /// This is the args of the typeck root.
     pub parent_args: &'tcx [GenericArg<'tcx>],
-    // TODO: why
+
+    /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut`
+    /// implementations must be distinguished since the former takes the closure's
+    /// upvars by move, and the latter takes the closure's upvars by ref.
+    ///
+    /// This field distinguishes these fields so that codegen can select the right
+    /// body for the coroutine. This has the same type representation as the closure
+    /// kind: `i8`/`i16`/`i32`.
+    ///
+    /// For regular coroutines, this field will always just be `()`.
     pub kind_ty: Ty<'tcx>,
+
     pub resume_ty: Ty<'tcx>,
     pub yield_ty: Ty<'tcx>,
     pub return_ty: Ty<'tcx>,
+
     /// The interior type of the coroutine.
     /// Represents all types that are stored in locals
     /// in the coroutine's body.
     pub witness: Ty<'tcx>,
+
     /// The upvars captured by the closure. Remains an inference variable
     /// until the upvar analysis, which happens late in HIR typeck.
     pub tupled_upvars_ty: Ty<'tcx>,
@@ -556,7 +588,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
         self.split().parent_args
     }
 
-    // TODO:
+    // Returns the kind of the coroutine. See docs on the `kind_ty` field.
     pub fn kind_ty(self) -> Ty<'tcx> {
         self.split().kind_ty
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index 65ff85a9669..41a4edfc03b 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -539,7 +539,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
                 )
             }
             mir::AggregateKind::CoroutineClosure(..) => {
-                todo!("FIXME(async_closure): Lower these to SMIR")
+                todo!("FIXME(async_closures): Lower these to SMIR")
             }
         }
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 3c1858e920b..066348dcb67 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -383,7 +383,7 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
                 tables.closure_def(*def_id),
                 generic_args.stable(tables),
             )),
-            ty::CoroutineClosure(..) => todo!("/* TODO */"),
+            ty::CoroutineClosure(..) => todo!("FIXME(async_closures): Lower these to SMIR"),
             ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine(
                 tables.coroutine_def(*def_id),
                 generic_args.stable(tables),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 587eb1c7cc5..4203cb29db6 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -321,6 +321,7 @@ symbols! {
         TyCtxt,
         TyKind,
         Unknown,
+        Upvars,
         Vec,
         VecDeque,
         Wrapper,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 8451fbcc434..7052fd776b0 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -190,7 +190,9 @@ pub(super) trait GoalKind<'tcx>:
         kind: ty::ClosureKind,
     ) -> QueryResult<'tcx>;
 
-    /// TODO:
+    /// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which
+    /// is used internally to delay computation for async closures until after
+    /// upvar analysis is performed in HIR typeck.
     fn consider_builtin_async_fn_kind_helper_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
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 0699026117d..dbf3e4876a9 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -8,6 +8,7 @@ use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::{
     self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
+use rustc_span::sym;
 
 use crate::solve::EvalCtxt;
 
@@ -274,7 +275,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
             Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
         }
 
-        // Coroutine closures don't implement `Fn` traits the normal way.
+        // Coroutine-closures don't implement `Fn` traits the normal way.
         ty::CoroutineClosure(..) => Err(NoSolution),
 
         ty::Bool
@@ -341,11 +342,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                     vec![],
                 ))
             } else {
-                let helper_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
-                // FIXME(async_closures): Make this into a lang item.
+                let async_fn_kind_trait_def_id =
+                    tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
                 let upvars_projection_def_id = tcx
-                    .associated_items(helper_trait_def_id)
-                    .in_definition_order()
+                    .associated_items(async_fn_kind_trait_def_id)
+                    .filter_by_name_unhygienic(sym::Upvars)
                     .next()
                     .unwrap()
                     .def_id;
@@ -375,7 +376,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                     vec![
                         ty::TraitRef::new(
                             tcx,
-                            helper_trait_def_id,
+                            async_fn_kind_trait_def_id,
                             [kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
                         )
                         .to_predicate(tcx),
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index db1e89ae72f..a8d6b9812be 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -2461,12 +2461,13 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
     let goal_kind =
         tcx.async_fn_trait_kind_from_def_id(obligation.predicate.trait_def_id(tcx)).unwrap();
 
-    let helper_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
+    let async_fn_kind_helper_trait_def_id =
+        tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
     nested.push(obligation.with(
         tcx,
         ty::TraitRef::new(
             tcx,
-            helper_trait_def_id,
+            async_fn_kind_helper_trait_def_id,
             [kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
         ),
     ));
@@ -2476,9 +2477,12 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
         ty::ClosureKind::FnOnce => tcx.lifetimes.re_static,
     };
 
-    // FIXME(async_closures): Make this into a lang item.
-    let upvars_projection_def_id =
-        tcx.associated_items(helper_trait_def_id).in_definition_order().next().unwrap().def_id;
+    let upvars_projection_def_id = tcx
+        .associated_items(async_fn_kind_helper_trait_def_id)
+        .filter_by_name_unhygienic(sym::Upvars)
+        .next()
+        .unwrap()
+        .def_id;
 
     // FIXME(async_closures): Confirmation is kind of a mess here. Ideally,
     // we'd short-circuit when we know that the goal_kind >= closure_kind, and not
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 5941fce8825..a4fe572067b 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -202,7 +202,11 @@ pub enum TyKind<I: Interner> {
     /// `ClosureArgs` for more details.
     Closure(I::DefId, I::GenericArgs),
 
-    /// TODO
+    /// The anonymous type of a closure. Used to represent the type of `async |a| a`.
+    ///
+    /// Coroutine-closure args contain both the - potentially substituted - generic
+    /// parameters of its parent and some synthetic parameters. See the documentation
+    /// for `CoroutineClosureArgs` for more details.
     CoroutineClosure(I::DefId, I::GenericArgs),
 
     /// The anonymous type of a coroutine. Used to represent the type of
diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs
index b11d5643990..efbe9d164c3 100644
--- a/library/core/src/ops/async_function.rs
+++ b/library/core/src/ops/async_function.rs
@@ -108,9 +108,26 @@ mod impls {
 }
 
 mod internal_implementation_detail {
-    // TODO: needs a detailed explanation
+    /// A helper trait that is used to enforce that the `ClosureKind` of a goal
+    /// is within the capabilities of a `CoroutineClosure`, and which allows us
+    /// to delay the projection of the tupled upvar types until after upvar
+    /// analysis is complete.
+    ///
+    /// The `Self` type is expected to be the `kind_ty` of the coroutine-closure,
+    /// and thus either `?0` or `i8`/`i16`/`i32` (see docs for `ClosureKind`
+    /// for an explanation of that). The `GoalKind` is also the same type, but
+    /// representing the kind of the trait that the closure is being called with.
     #[cfg_attr(not(bootstrap), lang = "async_fn_kind_helper")]
     trait AsyncFnKindHelper<GoalKind> {
-        type Assoc<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
+        // Projects a set of closure inputs (arguments), a region, and a set of upvars
+        // (by move and by ref) to the upvars that we expect the coroutine to have
+        // according to the `GoalKind` parameter above.
+        //
+        // The `Upvars` parameter should be the upvars of the parent coroutine-closure,
+        // and the `BorrowedUpvarsAsFnPtr` will be a function pointer that has the shape
+        // `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.
+        type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
     }
 }
diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
index c02bac2d7dd..2a3e382e118 100644
--- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
+++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
@@ -4,7 +4,8 @@
 fn foo() -> Box<dyn std::future::Future<Output = u32>> {
     let x = 0u32;
     Box::new((async || x)())
-    //~^ ERROR closure may outlive the current function, but it borrows `x`, which is owned by the current function
+    //~^ ERROR cannot return value referencing local variable `x`
+    //~| ERROR cannot return value referencing temporary value
 }
 
 fn main() {
diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
index 87851e1ae5b..be67c78221a 100644
--- a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
+++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
@@ -1,21 +1,21 @@
-error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
-  --> $DIR/async-borrowck-escaping-closure-error.rs:6:15
+error[E0515]: cannot return value referencing local variable `x`
+  --> $DIR/async-borrowck-escaping-closure-error.rs:6:5
    |
 LL |     Box::new((async || x)())
-   |               ^^^^^^^^ - `x` is borrowed here
-   |               |
-   |               may outlive borrowed value `x`
-   |
-note: closure is returned here
+   |     ^^^^^^^^^------------^^^
+   |     |        |
+   |     |        `x` is borrowed here
+   |     returns a value referencing data owned by the current function
+
+error[E0515]: cannot return value referencing temporary value
   --> $DIR/async-borrowck-escaping-closure-error.rs:6:5
    |
 LL |     Box::new((async || x)())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
-   |
-LL |     Box::new((async move || x)())
-   |                     ++++
+   |     ^^^^^^^^^------------^^^
+   |     |        |
+   |     |        temporary value created here
+   |     returns a value referencing data owned by the current function
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0373`.
+For more information about this error, try `rustc --explain E0515`.
diff --git a/tests/ui/async-await/async-closures/higher-ranked.rs b/tests/ui/async-await/async-closures/higher-ranked.rs
index f0bdcf691ae..5bbcc7041a8 100644
--- a/tests/ui/async-await/async-closures/higher-ranked.rs
+++ b/tests/ui/async-await/async-closures/higher-ranked.rs
@@ -1,12 +1,10 @@
 // edition:2021
+// check-pass
 
 #![feature(async_closure)]
 
 fn main() {
     let x = async move |x: &str| {
-        //~^ ERROR lifetime may not live long enough
-        // This error is proof that the `&str` type is higher-ranked.
-        // This won't work until async closures are fully impl'd.
         println!("{x}");
     };
 }
diff --git a/tests/ui/async-await/async-closures/higher-ranked.stderr b/tests/ui/async-await/async-closures/higher-ranked.stderr
deleted file mode 100644
index fb02a15b079..00000000000
--- a/tests/ui/async-await/async-closures/higher-ranked.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/higher-ranked.rs:6:34
-   |
-LL |       let x = async move |x: &str| {
-   |  ____________________________-___-_^
-   | |                            |   |
-   | |                            |   return type of closure `{async closure body@$DIR/higher-ranked.rs:6:34: 11:6}` contains a lifetime `'2`
-   | |                            let's call the lifetime of this reference `'1`
-LL | |
-LL | |         // This error is proof that the `&str` type is higher-ranked.
-LL | |         // This won't work until async closures are fully impl'd.
-LL | |         println!("{x}");
-LL | |     };
-   | |_____^ returning this value requires that `'1` must outlive `'2`
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
index 2d453e7891e..904d28fb0a7 100644
--- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs
@@ -12,7 +12,8 @@ pub async fn async_fn(x: &mut i32) -> &i32 {
 
 pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
     (async move || {
-        //~^ captured variable cannot escape `FnMut` closure body
+        //~^ ERROR lifetime may not live long enough
+        //~| ERROR temporary value dropped while borrowed
         let y = &*x;
         *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
         y
@@ -21,7 +22,8 @@ pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
 
 pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
     (async move || -> &i32 {
-        //~^ captured variable cannot escape `FnMut` closure body
+        //~^ ERROR lifetime may not live long enough
+        //~| ERROR temporary value dropped while borrowed
         let y = &*x;
         *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
         y
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
index 9120d78164e..bdf2820887c 100644
--- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
@@ -11,7 +11,7 @@ LL |     y
    |     - returning this value requires that `*x` is borrowed for `'1`
 
 error[E0506]: cannot assign to `*x` because it is borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:17:9
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:18:9
    |
 LL |         let y = &*x;
    |                 --- `*x` is borrowed here
@@ -22,61 +22,92 @@ LL |         y
 LL |     })()
    |     - return type of async closure is &'1 i32
 
-error: captured variable cannot escape `FnMut` closure body
+error: lifetime may not live long enough
   --> $DIR/issue-74072-lifetime-name-annotations.rs:14:20
    |
-LL |   pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
-   |                        - variable defined here
 LL |       (async move || {
-   |  __________________-_^
-   | |                  |
-   | |                  inferred to be a `FnMut` closure
+   |  ______-------------_^
+   | |      |           |
+   | |      |           return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:14:20: 20:6}` contains a lifetime `'2`
+   | |      lifetime `'1` represents this closure's body
+LL | |
 LL | |
 LL | |         let y = &*x;
-   | |                   - variable captured here
 LL | |         *x += 1;
 LL | |         y
 LL | |     })()
-   | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
+   | |_____^ returning this value requires that `'1` must outlive `'2`
+   |
+   = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:14:5
    |
-   = note: `FnMut` closures only have access to their captured variables while they are executing...
-   = note: ...therefore, they cannot allow references to captured variables to escape
+LL |    pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
+   |                            - let's call the lifetime of this reference `'1`
+LL | //     (async move || {
+LL | ||
+LL | ||
+LL | ||         let y = &*x;
+LL | ||         *x += 1;
+LL | ||         y
+LL | ||     })()
+   | ||______^_- argument requires that borrow lasts for `'1`
+   | |_______|
+   |         creates a temporary value which is freed while still in use
+LL |    }
+   |    - temporary value is freed at the end of this statement
 
 error[E0506]: cannot assign to `*x` because it is borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:26:9
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:28:9
    |
-LL |     (async move || -> &i32 {
-   |                       - let's call the lifetime of this reference `'1`
-LL |
 LL |         let y = &*x;
    |                 --- `*x` is borrowed here
 LL |         *x += 1;
    |         ^^^^^^^ `*x` is assigned to here but it was already borrowed
 LL |         y
    |         - returning this value requires that `*x` is borrowed for `'1`
+LL |     })()
+   |     - return type of async closure is &'1 i32
 
-error: captured variable cannot escape `FnMut` closure body
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:23:28
+error: lifetime may not live long enough
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:24:28
    |
-LL |   pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
-   |                                             - variable defined here
 LL |       (async move || -> &i32 {
-   |  __________________________-_^
-   | |                          |
-   | |                          inferred to be a `FnMut` closure
+   |  ______---------------------_^
+   | |      |                |
+   | |      |                return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:24:28: 30:6}` contains a lifetime `'2`
+   | |      lifetime `'1` represents this closure's body
+LL | |
 LL | |
 LL | |         let y = &*x;
-   | |                   - variable captured here
 LL | |         *x += 1;
 LL | |         y
 LL | |     })()
-   | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
+   | |_____^ returning this value requires that `'1` must outlive `'2`
+   |
+   = note: closure implements `FnMut`, so references to captured variables can't escape the closure
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:24:5
    |
-   = note: `FnMut` closures only have access to their captured variables while they are executing...
-   = note: ...therefore, they cannot allow references to captured variables to escape
+LL |    pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
+   |                                                 - let's call the lifetime of this reference `'1`
+LL | //     (async move || -> &i32 {
+LL | ||
+LL | ||
+LL | ||         let y = &*x;
+LL | ||         *x += 1;
+LL | ||         y
+LL | ||     })()
+   | ||______^_- argument requires that borrow lasts for `'1`
+   | |_______|
+   |         creates a temporary value which is freed while still in use
+LL |    }
+   |    - temporary value is freed at the end of this statement
 
 error[E0506]: cannot assign to `*x` because it is borrowed
-  --> $DIR/issue-74072-lifetime-name-annotations.rs:34:9
+  --> $DIR/issue-74072-lifetime-name-annotations.rs:36:9
    |
 LL |         let y = &*x;
    |                 --- `*x` is borrowed here
@@ -87,6 +118,7 @@ LL |         y
 LL |     }
    |     - return type of async block is &'1 i32
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0506`.
+Some errors have detailed explanations: E0506, E0716.
+For more information about an error, try `rustc --explain E0506`.
diff --git a/tests/ui/closures/binder/async-closure-with-binder.rs b/tests/ui/closures/binder/async-closure-with-binder.rs
index 4fa599d37cb..69d30f369e9 100644
--- a/tests/ui/closures/binder/async-closure-with-binder.rs
+++ b/tests/ui/closures/binder/async-closure-with-binder.rs
@@ -1,8 +1,9 @@
 // edition:2021
+// check-pass
+
 #![feature(closure_lifetime_binder)]
 #![feature(async_closure)]
+
 fn main() {
-    for<'a> async || ();
-    //~^ ERROR `for<...>` binders on `async` closures are not currently supported
-    //~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
+    for<'a> async || -> () {};
 }
diff --git a/tests/ui/closures/binder/async-closure-with-binder.stderr b/tests/ui/closures/binder/async-closure-with-binder.stderr
deleted file mode 100644
index 1d4628b1a49..00000000000
--- a/tests/ui/closures/binder/async-closure-with-binder.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error: `for<...>` binders on `async` closures are not currently supported
-  --> $DIR/async-closure-with-binder.rs:5:5
-   |
-LL |     for<'a> async || ();
-   |     ^^^^^^^
-
-error: implicit types in closure signatures are forbidden when `for<...>` is present
-  --> $DIR/async-closure-with-binder.rs:5:5
-   |
-LL |     for<'a> async || ();
-   |     -------^^^^^^^^^
-   |     |
-   |     `for<...>` is here
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index 3065f83ea3d..dc4ec5d3ee2 100644
--- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -18,25 +18,21 @@ help: use parentheses to call this function
 LL |     bar(foo());
    |            ++
 
-error[E0277]: `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
+error[E0277]: `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9
    |
 LL |     bar(async_closure);
-   |     --- ^^^^^^^^^^^^^ `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
+   |     --- ^^^^^^^^^^^^^ `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Future` is not implemented for closure `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}`
-   = note: {closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited
+   = help: the trait `Future` is not implemented for `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}`
+   = note: {coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
    |
 LL | fn bar(f: impl Future<Output=()>) {}
    |                ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
-help: use parentheses to call this closure
-   |
-LL |     bar(async_closure());
-   |                      ++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr
index 61d27ec69f4..c1cbefac828 100644
--- a/tests/ui/symbol-names/basic.legacy.stderr
+++ b/tests/ui/symbol-names/basic.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN5basic4main17h9308686d0228fa1dE)
+error: symbol-name(_ZN5basic4main17h6fc0c8d27b1a289fE)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic::main::h9308686d0228fa1d)
+error: demangling(basic::main::h6fc0c8d27b1a289f)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr
index eb65f3b58ff..7dd68e6e3a8 100644
--- a/tests/ui/symbol-names/issue-60925.legacy.stderr
+++ b/tests/ui/symbol-names/issue-60925.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h84ab5dafbd2a1508E)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hab58a402db4ebf3aE)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h84ab5dafbd2a1508)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hab58a402db4ebf3a)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]