about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-01 21:07:49 +0000
committerbors <bors@rust-lang.org>2025-08-01 21:07:49 +0000
commit63f6845e570305a92eaf855897768617366164d6 (patch)
tree373dbe2880f908756d25b76e9163fbb5e19f120f
parent4b55fe199cfe9c710555a5af7f2a49491ad38254 (diff)
parente9765781b2857da90161157a3fc523f9e1d58848 (diff)
downloadrust-63f6845e570305a92eaf855897768617366164d6.tar.gz
rust-63f6845e570305a92eaf855897768617366164d6.zip
Auto merge of #144458 - compiler-errors:no-witness-mini, r=lcnr
Remove the witness type from coroutine *args* (without actually removing the type)

This does as much of rust-lang/rust#144157 as we can without having to break rust-lang/rust#143545 and/or introduce some better way of handling higher ranked assumptions.

Namely, it:
* Stalls coroutines based off of the *coroutine* type rather than the witness type.
* Reworks the dtorck constraint hack to not rely on the witness type.
* Removes the witness type from the args of the coroutine, eagerly creating the type for nested obligations when needed (auto/clone impls).

I'll experiment with actually removing the witness type in a follow-up.

r? lcnr
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs5
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs29
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs8
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs20
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs64
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs16
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs43
-rw-r--r--compiler/rustc_type_ir/src/flags.rs11
-rw-r--r--compiler/rustc_type_ir/src/ty_kind/closure.rs27
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir8
-rw-r--r--tests/ui/async-await/async-closures/def-path.stderr4
-rw-r--r--tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr26
-rw-r--r--tests/ui/async-await/issue-70818.rs1
-rw-r--r--tests/ui/async-await/issue-70818.stderr23
-rw-r--r--tests/ui/async-await/issue-86507.stderr2
-rw-r--r--tests/ui/coroutine/clone-impl-async.rs6
-rw-r--r--tests/ui/coroutine/clone-impl-async.stderr132
-rw-r--r--tests/ui/coroutine/clone-impl-static.stderr12
-rw-r--r--tests/ui/coroutine/clone-impl.rs1
-rw-r--r--tests/ui/coroutine/clone-impl.stderr88
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-2.stderr4
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-3.stderr2
-rw-r--r--tests/ui/coroutine/ref-upvar-not-send.stderr14
-rw-r--r--tests/ui/impl-trait/issues/issue-55872-2.rs1
-rw-r--r--tests/ui/impl-trait/issues/issue-55872-2.stderr10
-rw-r--r--tests/ui/impl-trait/issues/issue-55872-3.rs1
-rw-r--r--tests/ui/impl-trait/issues/issue-55872-3.stderr17
32 files changed, 273 insertions, 335 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 99392ea1915..eb31b5de05d 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -86,7 +86,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         // them with fresh ty vars.
                         resume_ty: next_ty_var(),
                         yield_ty: next_ty_var(),
-                        witness: next_ty_var(),
                     },
                 )
                 .args,
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 31e9c3b80fb..e2462c2d465 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -379,20 +379,14 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         // for info on the usage of each of these fields.
         let dummy_args = match kind {
             ClosureKind::Closure => &["<closure_kind>", "<closure_signature>", "<upvars>"][..],
-            ClosureKind::Coroutine(_) => &[
-                "<coroutine_kind>",
-                "<resume_ty>",
-                "<yield_ty>",
-                "<return_ty>",
-                "<witness>",
-                "<upvars>",
-            ][..],
+            ClosureKind::Coroutine(_) => {
+                &["<coroutine_kind>", "<resume_ty>", "<yield_ty>", "<return_ty>", "<upvars>"][..]
+            }
             ClosureKind::CoroutineClosure(_) => &[
                 "<closure_kind>",
                 "<closure_signature_parts>",
                 "<upvars>",
                 "<bound_captures_by_ref>",
-                "<witness>",
             ][..],
         };
 
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index a413f805873..82b7c578a1f 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -161,8 +161,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Resume type defaults to `()` if the coroutine has no argument.
                 let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
 
-                let interior = Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args);
-
                 // Coroutines that come from coroutine closures have not yet determined
                 // their kind ty, so make a fresh infer var which will be constrained
                 // later during upvar analysis. Regular coroutines always have the kind
@@ -182,7 +180,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         resume_ty,
                         yield_ty,
                         return_ty: liberated_sig.output(),
-                        witness: interior,
                         tupled_upvars_ty,
                     },
                 );
@@ -210,7 +207,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 };
                 // Compute all of the variables that will be used to populate the coroutine.
                 let resume_ty = self.next_ty_var(expr_span);
-                let interior = self.next_ty_var(expr_span);
 
                 let closure_kind_ty = match expected_kind {
                     Some(kind) => Ty::from_closure_kind(tcx, kind),
@@ -243,7 +239,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ),
                         tupled_upvars_ty,
                         coroutine_captures_by_ref_ty,
-                        coroutine_witness_ty: interior,
                     },
                 );
 
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 7d34d8df3f3..b02abb5ab43 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -96,14 +96,12 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg
                 signature_parts_ty,
                 tupled_upvars_ty,
                 coroutine_captures_by_ref_ty,
-                coroutine_witness_ty,
             ] => ty::CoroutineClosureArgsParts {
                 parent_args,
                 closure_kind_ty: closure_kind_ty.expect_ty(),
                 signature_parts_ty: signature_parts_ty.expect_ty(),
                 tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
                 coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(),
-                coroutine_witness_ty: coroutine_witness_ty.expect_ty(),
             },
             _ => bug!("closure args missing synthetics"),
         }
@@ -111,23 +109,16 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg
 
     fn split_coroutine_args(self) -> ty::CoroutineArgsParts<TyCtxt<'tcx>> {
         match self[..] {
-            [
-                ref parent_args @ ..,
-                kind_ty,
-                resume_ty,
-                yield_ty,
-                return_ty,
-                witness,
-                tupled_upvars_ty,
-            ] => ty::CoroutineArgsParts {
-                parent_args,
-                kind_ty: kind_ty.expect_ty(),
-                resume_ty: resume_ty.expect_ty(),
-                yield_ty: yield_ty.expect_ty(),
-                return_ty: return_ty.expect_ty(),
-                witness: witness.expect_ty(),
-                tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
-            },
+            [ref parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => {
+                ty::CoroutineArgsParts {
+                    parent_args,
+                    kind_ty: kind_ty.expect_ty(),
+                    resume_ty: resume_ty.expect_ty(),
+                    yield_ty: yield_ty.expect_ty(),
+                    return_ty: return_ty.expect_ty(),
+                    tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
+                }
+            }
             _ => bug!("coroutine args missing synthetics"),
         }
     }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 5c44b10ba71..71eac294f15 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -913,9 +913,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                         " yield_ty=",
                         print(args.as_coroutine().yield_ty()),
                         " return_ty=",
-                        print(args.as_coroutine().return_ty()),
-                        " witness=",
-                        print(args.as_coroutine().witness())
+                        print(args.as_coroutine().return_ty())
                     );
                 }
 
@@ -1035,9 +1033,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                         " upvar_tys=",
                         print(args.as_coroutine_closure().tupled_upvars_ty()),
                         " coroutine_captures_by_ref_ty=",
-                        print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()),
-                        " coroutine_witness_ty=",
-                        print(args.as_coroutine_closure().coroutine_witness_ty())
+                        print(args.as_coroutine_closure().coroutine_captures_by_ref_ty())
                     );
                 }
                 p!("}}");
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index c0bebdf6fb6..faa86734d08 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -75,9 +75,16 @@ where
             Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
         }
 
-        ty::Coroutine(_, args) => {
+        ty::Coroutine(def_id, args) => {
             let coroutine_args = args.as_coroutine();
-            Ok(ty::Binder::dummy(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]))
+            Ok(ty::Binder::dummy(vec![
+                coroutine_args.tupled_upvars_ty(),
+                Ty::new_coroutine_witness(
+                    ecx.cx(),
+                    def_id,
+                    ecx.cx().mk_args(coroutine_args.parent_args().as_slice()),
+                ),
+            ]))
         }
 
         ty::CoroutineWitness(def_id, args) => Ok(ecx
@@ -245,7 +252,14 @@ where
             Movability::Movable => {
                 if ecx.cx().features().coroutine_clone() {
                     let coroutine = args.as_coroutine();
-                    Ok(ty::Binder::dummy(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]))
+                    Ok(ty::Binder::dummy(vec![
+                        coroutine.tupled_upvars_ty(),
+                        Ty::new_coroutine_witness(
+                            ecx.cx(),
+                            def_id,
+                            ecx.cx().mk_args(coroutine.parent_args().as_slice()),
+                        ),
+                    ]))
                 } else {
                     Err(NoSolution)
                 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 650b85d99d2..31991565b0d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -229,7 +229,7 @@ where
         }
 
         // We need to make sure to stall any coroutines we are inferring to avoid query cycles.
-        if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
+        if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
             return cand;
         }
 
@@ -294,7 +294,7 @@ where
         }
 
         // We need to make sure to stall any coroutines we are inferring to avoid query cycles.
-        if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
+        if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
             return cand;
         }
 
@@ -1432,11 +1432,8 @@ where
         self.merge_trait_candidates(candidates)
     }
 
-    fn try_stall_coroutine_witness(
-        &mut self,
-        self_ty: I::Ty,
-    ) -> Option<Result<Candidate<I>, NoSolution>> {
-        if let ty::CoroutineWitness(def_id, _) = self_ty.kind() {
+    fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {
+        if let ty::Coroutine(def_id, _) = self_ty.kind() {
             match self.typing_mode() {
                 TypingMode::Analysis {
                     defining_opaque_types_and_generators: stalled_generators,
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 01bdae7435d..3f628d80662 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -355,7 +355,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for StalledOnCoroutines<'tcx> {
             return ControlFlow::Continue(());
         }
 
-        if let ty::CoroutineWitness(def_id, _) = *ty.kind()
+        if let ty::Coroutine(def_id, _) = *ty.kind()
             && def_id.as_local().is_some_and(|def_id| self.stalled_coroutines.contains(&def_id))
         {
             ControlFlow::Break(())
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 38cfdcdc22d..b1b331d1b61 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -318,7 +318,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             })
         }
 
-        ty::Coroutine(_, args) => {
+        ty::Coroutine(def_id, args) => {
             // rust-lang/rust#49918: types can be constructed, stored
             // in the interior, and sit idle when coroutine yields
             // (and is subsequently dropped).
@@ -346,7 +346,10 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             // While we conservatively assume that all coroutines require drop
             // to avoid query cycles during MIR building, we can check the actual
             // witness during borrowck to avoid unnecessary liveness constraints.
-            if args.witness().needs_drop(tcx, tcx.erase_regions(typing_env)) {
+            let typing_env = tcx.erase_regions(typing_env);
+            if tcx.mir_coroutine_witnesses(def_id).is_some_and(|witness| {
+                witness.field_tys.iter().any(|field| field.ty.needs_drop(tcx, typing_env))
+            }) {
                 constraints.outlives.extend(args.upvar_tys().iter().map(ty::GenericArg::from));
                 constraints.outlives.push(args.resume_ty().into());
             }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 2c7089507a8..62795c8a3a6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -794,18 +794,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // The auto impl might apply; we don't know.
                     candidates.ambiguous = true;
                 }
-                ty::Coroutine(coroutine_def_id, _)
-                    if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
-                {
-                    match self.tcx().coroutine_movability(coroutine_def_id) {
-                        hir::Movability::Static => {
-                            // Immovable coroutines are never `Unpin`, so
-                            // suppress the normal auto-impl candidate for it.
+                ty::Coroutine(coroutine_def_id, _) => {
+                    if self.tcx().is_lang_item(def_id, LangItem::Unpin) {
+                        match self.tcx().coroutine_movability(coroutine_def_id) {
+                            hir::Movability::Static => {
+                                // Immovable coroutines are never `Unpin`, so
+                                // suppress the normal auto-impl candidate for it.
+                            }
+                            hir::Movability::Movable => {
+                                // Movable coroutines are always `Unpin`, so add an
+                                // unconditional builtin candidate with no sub-obligations.
+                                candidates.vec.push(BuiltinCandidate);
+                            }
                         }
-                        hir::Movability::Movable => {
-                            // Movable coroutines are always `Unpin`, so add an
-                            // unconditional builtin candidate.
-                            candidates.vec.push(BuiltinCandidate);
+                    } else {
+                        if self.should_stall_coroutine(coroutine_def_id) {
+                            candidates.ambiguous = true;
+                        } else {
+                            // Coroutines implement all other auto traits normally.
+                            candidates.vec.push(AutoImplCandidate);
                         }
                     }
                 }
@@ -842,12 +849,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
                 }
 
-                ty::CoroutineWitness(def_id, _) => {
-                    if self.should_stall_coroutine_witness(def_id) {
-                        candidates.ambiguous = true;
-                    } else {
-                        candidates.vec.push(AutoImplCandidate);
-                    }
+                ty::CoroutineWitness(..) => {
+                    candidates.vec.push(AutoImplCandidate);
                 }
 
                 ty::Bool
@@ -866,7 +869,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::FnPtr(..)
                 | ty::Closure(..)
                 | ty::CoroutineClosure(..)
-                | ty::Coroutine(..)
                 | ty::Never
                 | ty::Tuple(_)
                 | ty::UnsafeBinder(_) => {
@@ -1153,15 +1155,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::Ref(_, _, hir::Mutability::Mut) => {}
 
             ty::Coroutine(coroutine_def_id, args) => {
+                if self.should_stall_coroutine(coroutine_def_id) {
+                    candidates.ambiguous = true;
+                    return;
+                }
+
                 match self.tcx().coroutine_movability(coroutine_def_id) {
                     hir::Movability::Static => {}
                     hir::Movability::Movable => {
                         if self.tcx().features().coroutine_clone() {
                             let resolved_upvars =
                                 self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
-                            let resolved_witness =
-                                self.infcx.shallow_resolve(args.as_coroutine().witness());
-                            if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
+                            if resolved_upvars.is_ty_var() {
                                 // Not yet resolved.
                                 candidates.ambiguous = true;
                             } else {
@@ -1194,12 +1199,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
 
-            ty::CoroutineWitness(coroutine_def_id, _) => {
-                if self.should_stall_coroutine_witness(coroutine_def_id) {
-                    candidates.ambiguous = true;
-                } else {
-                    candidates.vec.push(SizedCandidate);
-                }
+            ty::CoroutineWitness(..) => {
+                candidates.vec.push(SizedCandidate);
             }
 
             // Fallback to whatever user-defined impls or param-env clauses exist in this case.
@@ -1238,7 +1239,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::RawPtr(..)
             | ty::Char
             | ty::Ref(..)
-            | ty::Coroutine(..)
             | ty::Array(..)
             | ty::Closure(..)
             | ty::CoroutineClosure(..)
@@ -1247,14 +1247,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 candidates.vec.push(SizedCandidate);
             }
 
-            ty::CoroutineWitness(coroutine_def_id, _) => {
-                if self.should_stall_coroutine_witness(coroutine_def_id) {
+            ty::Coroutine(coroutine_def_id, _) => {
+                if self.should_stall_coroutine(coroutine_def_id) {
                     candidates.ambiguous = true;
                 } else {
                     candidates.vec.push(SizedCandidate);
                 }
             }
 
+            ty::CoroutineWitness(..) => {
+                candidates.vec.push(SizedCandidate);
+            }
+
             // Conditionally `Sized`.
             ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => {
                 candidates.vec.push(SizedCandidate);
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index d7c3543cb3f..7ea1548f8f2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2196,7 +2196,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                                 args.as_coroutine()
                                     .upvar_tys()
                                     .iter()
-                                    .chain([args.as_coroutine().witness()])
+                                    .chain([Ty::new_coroutine_witness(
+                                        self.tcx(),
+                                        coroutine_def_id,
+                                        self.tcx().mk_args(args.as_coroutine().parent_args()),
+                                    )])
                                     .collect::<Vec<_>>(),
                             )
                         } else {
@@ -2327,9 +2331,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 ty::Binder::dummy(AutoImplConstituents { types: vec![ty], assumptions: vec![] })
             }
 
-            ty::Coroutine(_, args) => {
+            ty::Coroutine(def_id, args) => {
                 let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
-                let witness = args.as_coroutine().witness();
+                let witness = Ty::new_coroutine_witness(
+                    self.tcx(),
+                    def_id,
+                    self.tcx().mk_args(args.as_coroutine().parent_args()),
+                );
                 ty::Binder::dummy(AutoImplConstituents {
                     types: [ty].into_iter().chain(iter::once(witness)).collect(),
                     assumptions: vec![],
@@ -2841,7 +2849,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         obligations
     }
 
-    fn should_stall_coroutine_witness(&self, def_id: DefId) -> bool {
+    fn should_stall_coroutine(&self, def_id: DefId) -> bool {
         match self.infcx.typing_mode() {
             TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators } => {
                 def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index c3b04c20f4b..13d56889bd1 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -101,9 +101,6 @@ fn has_significant_drop_raw<'tcx>(
 struct NeedsDropTypes<'tcx, F> {
     tcx: TyCtxt<'tcx>,
     typing_env: ty::TypingEnv<'tcx>,
-    /// Whether to reveal coroutine witnesses, this is set
-    /// to `false` unless we compute `needs_drop` for a coroutine witness.
-    reveal_coroutine_witnesses: bool,
     query_ty: Ty<'tcx>,
     seen_tys: FxHashSet<Ty<'tcx>>,
     /// A stack of types left to process, and the recursion depth when we
@@ -115,6 +112,15 @@ struct NeedsDropTypes<'tcx, F> {
     adt_components: F,
     /// Set this to true if an exhaustive list of types involved in
     /// drop obligation is requested.
+    // FIXME: Calling this bool `exhaustive` is confusing and possibly a footgun,
+    // since it does two things: It makes the iterator yield *all* of the types
+    // that need drop, and it also affects the computation of the drop components
+    // on `Coroutine`s. The latter is somewhat confusing, and probably should be
+    // a function of `typing_env`. See the HACK comment below for why this is
+    // necessary. If this isn't possible, then we probably should turn this into
+    // a `NeedsDropMode` so that we can have a variant like `CollectAllSignificantDrops`,
+    // which will more accurately indicate that we want *all* of the *significant*
+    // drops, which are the two important behavioral changes toggled by this bool.
     exhaustive: bool,
 }
 
@@ -131,7 +137,6 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
         Self {
             tcx,
             typing_env,
-            reveal_coroutine_witnesses: exhaustive,
             seen_tys,
             query_ty: ty,
             unchecked_tys: vec![(ty, 0)],
@@ -195,23 +200,27 @@ where
                     // for the coroutine witness and check whether any of the contained types
                     // need to be dropped, and only require the captured types to be live
                     // if they do.
-                    ty::Coroutine(_, args) => {
-                        if self.reveal_coroutine_witnesses {
-                            queue_type(self, args.as_coroutine().witness());
+                    ty::Coroutine(def_id, args) => {
+                        // FIXME: See FIXME on `exhaustive` field above.
+                        if self.exhaustive {
+                            for upvar in args.as_coroutine().upvar_tys() {
+                                queue_type(self, upvar);
+                            }
+                            queue_type(self, args.as_coroutine().resume_ty());
+                            if let Some(witness) = tcx.mir_coroutine_witnesses(def_id) {
+                                for field_ty in &witness.field_tys {
+                                    queue_type(
+                                        self,
+                                        EarlyBinder::bind(field_ty.ty).instantiate(tcx, args),
+                                    );
+                                }
+                            }
                         } else {
                             return Some(self.always_drop_component(ty));
                         }
                     }
-                    ty::CoroutineWitness(def_id, args) => {
-                        if let Some(witness) = tcx.mir_coroutine_witnesses(def_id) {
-                            self.reveal_coroutine_witnesses = true;
-                            for field_ty in &witness.field_tys {
-                                queue_type(
-                                    self,
-                                    EarlyBinder::bind(field_ty.ty).instantiate(tcx, args),
-                                );
-                            }
-                        }
+                    ty::CoroutineWitness(..) => {
+                        unreachable!("witness should be handled in parent");
                     }
 
                     ty::UnsafeBinder(bound_ty) => {
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index d7b9e0ca340..23b7f55fbbe 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -131,10 +131,7 @@ bitflags::bitflags! {
         /// Does this have any binders with bound vars (e.g. that need to be anonymized)?
         const HAS_BINDER_VARS             = 1 << 23;
 
-        /// Does this type have any coroutine witnesses in it?
-        // FIXME: This should probably be changed to track whether the type has any
-        // *coroutines* in it, though this will happen if we remove coroutine witnesses
-        // altogether.
+        /// Does this type have any coroutines in it?
         const HAS_TY_CORO                 = 1 << 24;
     }
 }
@@ -246,11 +243,13 @@ impl<I: Interner> FlagComputation<I> {
                 self.add_flags(TypeFlags::HAS_TY_PARAM);
             }
 
-            ty::Closure(_, args) | ty::Coroutine(_, args) | ty::CoroutineClosure(_, args) => {
+            ty::Closure(_, args)
+            | ty::CoroutineClosure(_, args)
+            | ty::CoroutineWitness(_, args) => {
                 self.add_args(args.as_slice());
             }
 
-            ty::CoroutineWitness(_, args) => {
+            ty::Coroutine(_, args) => {
                 self.add_flags(TypeFlags::HAS_TY_CORO);
                 self.add_args(args.as_slice());
             }
diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs
index d1ca9bdb7fb..c32f8339d0b 100644
--- a/compiler/rustc_type_ir/src/ty_kind/closure.rs
+++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs
@@ -101,7 +101,6 @@ use crate::{self as ty, Interner};
 ///   `yield` inside the coroutine.
 /// * `GR`: The "return type", which is the type of value returned upon
 ///   completion of the coroutine.
-/// * `GW`: The "coroutine witness".
 #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 pub struct ClosureArgs<I: Interner> {
@@ -239,8 +238,6 @@ pub struct CoroutineClosureArgsParts<I: Interner> {
     /// while the `tupled_upvars_ty`, representing the by-move version of the same
     /// captures, will be `(String,)`.
     pub coroutine_captures_by_ref_ty: I::Ty,
-    /// Witness type returned by the generator produced by this coroutine-closure.
-    pub coroutine_witness_ty: I::Ty,
 }
 
 impl<I: Interner> CoroutineClosureArgs<I> {
@@ -251,7 +248,6 @@ impl<I: Interner> CoroutineClosureArgs<I> {
                 parts.signature_parts_ty.into(),
                 parts.tupled_upvars_ty.into(),
                 parts.coroutine_captures_by_ref_ty.into(),
-                parts.coroutine_witness_ty.into(),
             ])),
         }
     }
@@ -292,7 +288,6 @@ impl<I: Interner> CoroutineClosureArgs<I> {
     }
 
     pub fn coroutine_closure_sig(self) -> ty::Binder<I, CoroutineClosureSignature<I>> {
-        let interior = self.coroutine_witness_ty();
         let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { panic!() };
         sig_tys.map_bound(|sig_tys| {
             let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else {
@@ -302,7 +297,6 @@ impl<I: Interner> CoroutineClosureArgs<I> {
                 panic!()
             };
             CoroutineClosureSignature {
-                interior,
                 tupled_inputs_ty,
                 resume_ty,
                 yield_ty,
@@ -318,10 +312,6 @@ impl<I: Interner> CoroutineClosureArgs<I> {
         self.split().coroutine_captures_by_ref_ty
     }
 
-    pub fn coroutine_witness_ty(self) -> I::Ty {
-        self.split().coroutine_witness_ty
-    }
-
     pub fn has_self_borrows(&self) -> bool {
         match self.coroutine_captures_by_ref_ty().kind() {
             ty::FnPtr(sig_tys, _) => sig_tys
@@ -361,7 +351,6 @@ impl<I: Interner> TypeVisitor<I> for HasRegionsBoundAt {
 #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 pub struct CoroutineClosureSignature<I: Interner> {
-    pub interior: I::Ty,
     pub tupled_inputs_ty: I::Ty,
     pub resume_ty: I::Ty,
     pub yield_ty: I::Ty,
@@ -407,7 +396,6 @@ impl<I: Interner> CoroutineClosureSignature<I> {
                 resume_ty: self.resume_ty,
                 yield_ty: self.yield_ty,
                 return_ty: self.return_ty,
-                witness: self.interior,
                 tupled_upvars_ty,
             },
         );
@@ -587,11 +575,6 @@ pub struct CoroutineArgsParts<I: Interner> {
     pub yield_ty: I::Ty,
     pub return_ty: I::Ty,
 
-    /// The interior type of the coroutine.
-    /// Represents all types that are stored in locals
-    /// in the coroutine's body.
-    pub witness: I::Ty,
-
     /// The upvars captured by the closure. Remains an inference variable
     /// until the upvar analysis, which happens late in HIR typeck.
     pub tupled_upvars_ty: I::Ty,
@@ -607,7 +590,6 @@ impl<I: Interner> CoroutineArgs<I> {
                 parts.resume_ty.into(),
                 parts.yield_ty.into(),
                 parts.return_ty.into(),
-                parts.witness.into(),
                 parts.tupled_upvars_ty.into(),
             ])),
         }
@@ -629,15 +611,6 @@ impl<I: Interner> CoroutineArgs<I> {
         self.split().kind_ty
     }
 
-    /// This describes the types that can be contained in a coroutine.
-    /// It will be a type variable initially and unified in the last stages of typeck of a body.
-    /// It contains a tuple of all the types that could end up on a coroutine frame.
-    /// The state transformation MIR pass may only produce layouts which mention types
-    /// in this tuple. Upvars are not counted here.
-    pub fn witness(self) -> I::Ty {
-        self.split().witness
-    }
-
     /// Returns an iterator over the list of types of captured paths by the coroutine.
     /// In case there was a type error in figuring out the types of the captured path, an
     /// empty iterator is returned.
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
index 109a41d1ef9..9bff257e063 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
@@ -9,10 +9,6 @@
                     std::future::ResumeTy,
                     (),
                     (),
-                    CoroutineWitness(
-                        DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
-                        [],
-                    ),
                     (),
                 ],
             ),
@@ -30,10 +26,6 @@
                     std::future::ResumeTy,
                     (),
                     (),
-                    CoroutineWitness(
-                        DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
-                        [],
-                    ),
                     (),
                 ],
             ),
diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr
index 58a5b0b79c4..a507fa69760 100644
--- a/tests/ui/async-await/async-closures/def-path.stderr
+++ b/tests/ui/async-await/async-closures/def-path.stderr
@@ -5,11 +5,11 @@ LL |     let x = async || {};
    |                      -- the expected `async` closure body
 LL |
 LL |     let () = x();
-   |         ^^   --- this expression has type `{static main::{closure#0}::{closure#0}<?16t> upvar_tys=?15t resume_ty=ResumeTy yield_ty=() return_ty=() witness={main::{closure#0}::{closure#0}}}`
+   |         ^^   --- this expression has type `{static main::{closure#0}::{closure#0}<?15t> upvar_tys=?14t resume_ty=ResumeTy yield_ty=() return_ty=()}`
    |         |
    |         expected `async` closure body, found `()`
    |
-   = note: expected `async` closure body `{static main::{closure#0}::{closure#0}<?16t> upvar_tys=?15t resume_ty=ResumeTy yield_ty=() return_ty=() witness={main::{closure#0}::{closure#0}}}`
+   = note: expected `async` closure body `{static main::{closure#0}::{closure#0}<?15t> upvar_tys=?14t resume_ty=ResumeTy yield_ty=() return_ty=()}`
                          found unit type `()`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr
index d1f2d9a0753..d1c88101618 100644
--- a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr
+++ b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr
@@ -21,30 +21,6 @@ LL |     Box::new(async { new(|| async { f().await }).await })
    = help: consider pinning your async block and casting it to a trait object
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0308]: mismatched types
-  --> $DIR/higher-ranked-auto-trait-6.rs:16:5
-   |
-LL |     Box::new(async { new(|| async { f().await }).await })
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}`
-              found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}`
-   = note: no two async blocks, even if identical, have the same type
-   = help: consider pinning your async block and casting it to a trait object
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0308]: mismatched types
-  --> $DIR/higher-ranked-auto-trait-6.rs:16:5
-   |
-LL |     Box::new(async { new(|| async { f().await }).await })
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}`
-              found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}`
-   = note: no two async blocks, even if identical, have the same type
-   = help: consider pinning your async block and casting it to a trait object
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs
index bc181de8d92..c11332fe7d8 100644
--- a/tests/ui/async-await/issue-70818.rs
+++ b/tests/ui/async-await/issue-70818.rs
@@ -4,6 +4,7 @@ use std::future::Future;
 fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
     //~^ ERROR future cannot be sent between threads safely
     async { (ty, ty1) }
+    //~^ ERROR future cannot be sent between threads safely
 }
 
 fn main() {}
diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr
index 8de6a825042..07fd20cdd77 100644
--- a/tests/ui/async-await/issue-70818.stderr
+++ b/tests/ui/async-await/issue-70818.stderr
@@ -1,4 +1,25 @@
 error: future cannot be sent between threads safely
+  --> $DIR/issue-70818.rs:6:5
+   |
+LL |     async { (ty, ty1) }
+   |     ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+   |
+note: captured value is not `Send`
+  --> $DIR/issue-70818.rs:6:18
+   |
+LL |     async { (ty, ty1) }
+   |                  ^^^ has type `U` which is not `Send`
+note: required by a bound in an opaque type
+  --> $DIR/issue-70818.rs:4:69
+   |
+LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+   |                                                                     ^^^^
+help: consider restricting type parameter `U` with trait `Send`
+   |
+LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+   |                  +++++++++++++++++++
+
+error: future cannot be sent between threads safely
   --> $DIR/issue-70818.rs:4:38
    |
 LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
@@ -14,5 +35,5 @@ help: consider restricting type parameter `U` with trait `Send`
 LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
    |                  +++++++++++++++++++
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr
index 6385a8c975e..c71801dcfc8 100644
--- a/tests/ui/async-await/issue-86507.stderr
+++ b/tests/ui/async-await/issue-86507.stderr
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
    |
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
-   = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
+   = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<dyn Future<Output = ()> + Send>>`
 help: consider further restricting type parameter `T` with trait `Sync`
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
diff --git a/tests/ui/coroutine/clone-impl-async.rs b/tests/ui/coroutine/clone-impl-async.rs
index 2794b167aa2..4e2b26d0295 100644
--- a/tests/ui/coroutine/clone-impl-async.rs
+++ b/tests/ui/coroutine/clone-impl-async.rs
@@ -9,7 +9,7 @@ use std::future::ready;
 
 struct NonClone;
 
-fn main() {
+fn local() {
     let inner_non_clone = async {
         let non_clone = NonClone;
         let () = ready(()).await;
@@ -34,7 +34,9 @@ fn main() {
     //~^ ERROR : Copy` is not satisfied
     check_clone(&maybe_copy_clone);
     //~^ ERROR : Clone` is not satisfied
+}
 
+fn non_local() {
     let inner_non_clone_fn = the_inner_non_clone_fn();
     check_copy(&inner_non_clone_fn);
     //~^ ERROR : Copy` is not satisfied
@@ -69,3 +71,5 @@ async fn the_maybe_copy_clone_fn() {}
 
 fn check_copy<T: Copy>(_x: &T) {}
 fn check_clone<T: Clone>(_x: &T) {}
+
+fn main() {}
diff --git a/tests/ui/coroutine/clone-impl-async.stderr b/tests/ui/coroutine/clone-impl-async.stderr
index 62bcce2fbcb..319a5ed3d8d 100644
--- a/tests/ui/coroutine/clone-impl-async.stderr
+++ b/tests/ui/coroutine/clone-impl-async.stderr
@@ -1,167 +1,155 @@
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied
-  --> $DIR/clone-impl-async.rs:18:16
+error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+  --> $DIR/clone-impl-async.rs:41:16
    |
-LL |     check_copy(&inner_non_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}`
+LL |     check_copy(&inner_non_clone_fn);
+   |     ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:72:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied
-  --> $DIR/clone-impl-async.rs:20:17
+error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+  --> $DIR/clone-impl-async.rs:43:17
    |
-LL |     check_clone(&inner_non_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}`
+LL |     check_clone(&inner_non_clone_fn);
+   |     ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:73:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied
-  --> $DIR/clone-impl-async.rs:27:16
+error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+  --> $DIR/clone-impl-async.rs:47:16
    |
-LL |     check_copy(&outer_non_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}`
+LL |     check_copy(&outer_non_clone_fn);
+   |     ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:72:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied
-  --> $DIR/clone-impl-async.rs:29:17
+error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+  --> $DIR/clone-impl-async.rs:49:17
    |
-LL |     check_clone(&outer_non_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}`
+LL |     check_clone(&outer_non_clone_fn);
+   |     ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:73:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied
-  --> $DIR/clone-impl-async.rs:33:16
+error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+  --> $DIR/clone-impl-async.rs:53:16
    |
-LL |     check_copy(&maybe_copy_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}`
+LL |     check_copy(&maybe_copy_clone_fn);
+   |     ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:72:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied
-  --> $DIR/clone-impl-async.rs:35:17
+error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+  --> $DIR/clone-impl-async.rs:55:17
    |
-LL |     check_clone(&maybe_copy_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}`
+LL |     check_clone(&maybe_copy_clone_fn);
+   |     ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:73:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
-  --> $DIR/clone-impl-async.rs:39:16
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied
+  --> $DIR/clone-impl-async.rs:18:5
    |
-LL |     check_copy(&inner_non_clone_fn);
-   |     ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
-   |     |
-   |     required by a bound introduced by this call
+LL |     check_copy(&inner_non_clone);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}`
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:72:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
-  --> $DIR/clone-impl-async.rs:41:17
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied
+  --> $DIR/clone-impl-async.rs:20:5
    |
-LL |     check_clone(&inner_non_clone_fn);
-   |     ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
-   |     |
-   |     required by a bound introduced by this call
+LL |     check_clone(&inner_non_clone);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}`
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:73:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
-  --> $DIR/clone-impl-async.rs:45:16
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied
+  --> $DIR/clone-impl-async.rs:27:5
    |
-LL |     check_copy(&outer_non_clone_fn);
-   |     ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
-   |     |
-   |     required by a bound introduced by this call
+LL |     check_copy(&outer_non_clone);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}`
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:72:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
-  --> $DIR/clone-impl-async.rs:47:17
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied
+  --> $DIR/clone-impl-async.rs:29:5
    |
-LL |     check_clone(&outer_non_clone_fn);
-   |     ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
-   |     |
-   |     required by a bound introduced by this call
+LL |     check_clone(&outer_non_clone);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}`
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:73:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
-  --> $DIR/clone-impl-async.rs:51:16
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied
+  --> $DIR/clone-impl-async.rs:33:5
    |
-LL |     check_copy(&maybe_copy_clone_fn);
-   |     ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
-   |     |
-   |     required by a bound introduced by this call
+LL |     check_copy(&maybe_copy_clone);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}`
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:72:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
-  --> $DIR/clone-impl-async.rs:53:17
+error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied
+  --> $DIR/clone-impl-async.rs:35:5
    |
-LL |     check_clone(&maybe_copy_clone_fn);
-   |     ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
-   |     |
-   |     required by a bound introduced by this call
+LL |     check_clone(&maybe_copy_clone);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}`
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:73:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr
index 9fb71fd5fd0..4df6b9759c3 100644
--- a/tests/ui/coroutine/clone-impl-static.stderr
+++ b/tests/ui/coroutine/clone-impl-static.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Copy` is not satisfied
-  --> $DIR/clone-impl-static.rs:14:16
+  --> $DIR/clone-impl-static.rs:14:5
    |
 LL |     check_copy(&generator);
-   |     ---------- ^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
-   |     |
-   |     required by a bound introduced by this call
+   |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
    |
 note: required by a bound in `check_copy`
   --> $DIR/clone-impl-static.rs:20:18
@@ -13,12 +11,10 @@ LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
 error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Clone` is not satisfied
-  --> $DIR/clone-impl-static.rs:16:17
+  --> $DIR/clone-impl-static.rs:16:5
    |
 LL |     check_clone(&generator);
-   |     ----------- ^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
-   |     |
-   |     required by a bound introduced by this call
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
    |
 note: required by a bound in `check_clone`
   --> $DIR/clone-impl-static.rs:21:19
diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs
index e528f031d52..9e04e256fc1 100644
--- a/tests/ui/coroutine/clone-impl.rs
+++ b/tests/ui/coroutine/clone-impl.rs
@@ -42,6 +42,7 @@ fn test3_upvars() {
     let clonable_0: Vec<u32> = Vec::new();
     let gen_clone_0 = #[coroutine]
     move || {
+        yield;
         drop(clonable_0);
     };
     check_copy(&gen_clone_0);
diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr
index 714e5aa3d9e..f316902a42d 100644
--- a/tests/ui/coroutine/clone-impl.stderr
+++ b/tests/ui/coroutine/clone-impl.stderr
@@ -1,59 +1,81 @@
 error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`
-  --> $DIR/clone-impl.rs:47:16
+  --> $DIR/clone-impl.rs:48:5
    |
 LL |     move || {
    |     ------- within this `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |                ^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec<u32>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec<u32>`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:45:14
+  --> $DIR/clone-impl.rs:46:14
    |
 LL |         drop(clonable_0);
    |              ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:91:18
+  --> $DIR/clone-impl.rs:92:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}`
-  --> $DIR/clone-impl.rs:73:16
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}`
+  --> $DIR/clone-impl.rs:60:5
    |
 LL |     move || {
-   |     ------- within this `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}`
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |                ^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}`, the trait `Copy` is not implemented for `Vec<u32>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}`, the trait `Copy` is not implemented for `Vec<char>`
+   |
+note: coroutine does not implement `Copy` as this value is used across a yield
+  --> $DIR/clone-impl.rs:57:9
+   |
+LL |         let v = vec!['a'];
+   |             - has type `Vec<char>` which does not implement `Copy`
+LL |         yield;
+   |         ^^^^^ yield occurs here, with `v` maybe used later
+note: required by a bound in `check_copy`
+  --> $DIR/clone-impl.rs:92:18
+   |
+LL | fn check_copy<T: Copy>(_x: &T) {}
+   |                  ^^^^ required by this bound in `check_copy`
+
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}`
+  --> $DIR/clone-impl.rs:74:5
+   |
+LL |     move || {
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}`
+...
+LL |     check_copy(&gen_clone_1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}`, the trait `Copy` is not implemented for `Vec<u32>`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:71:14
+  --> $DIR/clone-impl.rs:72:14
    |
 LL |         drop(clonable_1);
    |              ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:91:18
+  --> $DIR/clone-impl.rs:92:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`
-  --> $DIR/clone-impl.rs:85:16
+error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`
+  --> $DIR/clone-impl.rs:86:5
    |
 LL |     move || {
-   |     ------- within this `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`
 ...
 LL |     check_copy(&gen_non_clone);
-   |                ^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`, the trait `Copy` is not implemented for `NonClone`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`, the trait `Copy` is not implemented for `NonClone`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:83:14
+  --> $DIR/clone-impl.rs:84:14
    |
 LL |         drop(non_clonable);
    |              ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:91:18
+  --> $DIR/clone-impl.rs:92:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -63,22 +85,22 @@ LL + #[derive(Copy)]
 LL | struct NonClone;
    |
 
-error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`
-  --> $DIR/clone-impl.rs:87:17
+error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`
+  --> $DIR/clone-impl.rs:88:5
    |
 LL |     move || {
-   |     ------- within this `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`
+   |     ------- within this `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`
 ...
 LL |     check_clone(&gen_non_clone);
-   |                 ^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`, the trait `Clone` is not implemented for `NonClone`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`, the trait `Clone` is not implemented for `NonClone`
    |
 note: captured value does not implement `Clone`
-  --> $DIR/clone-impl.rs:83:14
+  --> $DIR/clone-impl.rs:84:14
    |
 LL |         drop(non_clonable);
    |              ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone`
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl.rs:92:19
+  --> $DIR/clone-impl.rs:93:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
@@ -88,28 +110,6 @@ LL + #[derive(Clone)]
 LL | struct NonClone;
    |
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}`
-  --> $DIR/clone-impl.rs:59:5
-   |
-LL |     move || {
-   |     ------- within this `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}`
-...
-LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}`, the trait `Copy` is not implemented for `Vec<char>`
-   |
-note: coroutine does not implement `Copy` as this value is used across a yield
-  --> $DIR/clone-impl.rs:56:9
-   |
-LL |         let v = vec!['a'];
-   |             - has type `Vec<char>` which does not implement `Copy`
-LL |         yield;
-   |         ^^^^^ yield occurs here, with `v` maybe used later
-note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:91:18
-   |
-LL | fn check_copy<T: Copy>(_x: &T) {}
-   |                  ^^^^ required by this bound in `check_copy`
-
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
index 8877d45ddda..11b78e3bcf8 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
@@ -9,7 +9,7 @@ LL | |         drop(a);
 LL | |     });
    | |______^ coroutine is not `Sync`
    |
-   = help: within `{main::{closure#0} upvar_tys=() resume_ty=() yield_ty=() return_ty=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync`
+   = help: within `{main::{closure#0} upvar_tys=() resume_ty=() yield_ty=() return_ty=()}`, the trait `Sync` is not implemented for `NotSync`
 note: coroutine is not `Sync` as this value is used across a yield
   --> $DIR/coroutine-print-verbose-2.rs:20:9
    |
@@ -34,7 +34,7 @@ LL | |         drop(a);
 LL | |     });
    | |______^ coroutine is not `Send`
    |
-   = help: within `{main::{closure#1} upvar_tys=() resume_ty=() yield_ty=() return_ty=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend`
+   = help: within `{main::{closure#1} upvar_tys=() resume_ty=() yield_ty=() return_ty=()}`, the trait `Send` is not implemented for `NotSend`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/coroutine-print-verbose-2.rs:27:9
    |
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr
index 4a1e5b078a8..135e8175793 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr
@@ -11,7 +11,7 @@ LL | |     };
    | |_____^ expected `()`, found coroutine
    |
    = note: expected unit type `()`
-              found coroutine `{main::{closure#0} upvar_tys=?4t resume_ty=() yield_ty=i32 return_ty=&'?1 str witness={main::{closure#0}}}`
+              found coroutine `{main::{closure#0} upvar_tys=?4t resume_ty=() yield_ty=i32 return_ty=&'?1 str}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr
index 892b5d261c2..3a5e8ec4dab 100644
--- a/tests/ui/coroutine/ref-upvar-not-send.stderr
+++ b/tests/ui/coroutine/ref-upvar-not-send.stderr
@@ -1,14 +1,13 @@
 error: coroutine cannot be sent between threads safely
-  --> $DIR/ref-upvar-not-send.rs:15:30
+  --> $DIR/ref-upvar-not-send.rs:15:5
    |
-LL |       assert_send(#[coroutine] move || {
-   |  ______________________________^
+LL | /     assert_send(#[coroutine] move || {
 LL | |
 LL | |
 LL | |         yield;
 LL | |         let _x = x;
 LL | |     });
-   | |_____^ coroutine is not `Send`
+   | |______^ coroutine is not `Send`
    |
    = help: the trait `Sync` is not implemented for `*mut ()`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
@@ -23,16 +22,15 @@ LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: coroutine cannot be sent between threads safely
-  --> $DIR/ref-upvar-not-send.rs:23:30
+  --> $DIR/ref-upvar-not-send.rs:23:5
    |
-LL |       assert_send(#[coroutine] move || {
-   |  ______________________________^
+LL | /     assert_send(#[coroutine] move || {
 LL | |
 LL | |
 LL | |         yield;
 LL | |         let _y = y;
 LL | |     });
-   | |_____^ coroutine is not `Send`
+   | |______^ coroutine is not `Send`
    |
    = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()`
 note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
diff --git a/tests/ui/impl-trait/issues/issue-55872-2.rs b/tests/ui/impl-trait/issues/issue-55872-2.rs
index a3b2225126a..aea00dd9e3d 100644
--- a/tests/ui/impl-trait/issues/issue-55872-2.rs
+++ b/tests/ui/impl-trait/issues/issue-55872-2.rs
@@ -12,7 +12,6 @@ impl<S> Bar for S {
     type E = impl std::marker::Send;
     fn foo<T>() -> Self::E {
         //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-        //~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
         async {}
     }
 }
diff --git a/tests/ui/impl-trait/issues/issue-55872-2.stderr b/tests/ui/impl-trait/issues/issue-55872-2.stderr
index 51a7dd00ade..91c2ecdc8a4 100644
--- a/tests/ui/impl-trait/issues/issue-55872-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-55872-2.stderr
@@ -4,13 +4,5 @@ error: type parameter `T` is part of concrete type but not used in parameter lis
 LL |     fn foo<T>() -> Self::E {
    |                    ^^^^^^^
 
-error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-2.rs:13:20
-   |
-LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-55872-3.rs b/tests/ui/impl-trait/issues/issue-55872-3.rs
index 763b4b9fd32..698e7f36234 100644
--- a/tests/ui/impl-trait/issues/issue-55872-3.rs
+++ b/tests/ui/impl-trait/issues/issue-55872-3.rs
@@ -14,7 +14,6 @@ impl<S> Bar for S {
     fn foo<T>() -> Self::E {
         //~^ ERROR : Copy` is not satisfied [E0277]
         //~| ERROR type parameter `T` is part of concrete type
-        //~| ERROR type parameter `T` is part of concrete type
         async {}
     }
 }
diff --git a/tests/ui/impl-trait/issues/issue-55872-3.stderr b/tests/ui/impl-trait/issues/issue-55872-3.stderr
index ce2dd7f02b4..5124c46baeb 100644
--- a/tests/ui/impl-trait/issues/issue-55872-3.stderr
+++ b/tests/ui/impl-trait/issues/issue-55872-3.stderr
@@ -1,26 +1,15 @@
-error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}: Copy` is not satisfied
-  --> $DIR/issue-55872-3.rs:14:20
-   |
-LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}`
-...
-LL |         async {}
-   |         -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` here
-
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
   --> $DIR/issue-55872-3.rs:14:20
    |
 LL |     fn foo<T>() -> Self::E {
    |                    ^^^^^^^
 
-error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}: Copy` is not satisfied
   --> $DIR/issue-55872-3.rs:14:20
    |
 LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   |                    ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.