about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2024-04-23 17:25:16 +0200
committerGitHub <noreply@github.com>2024-04-23 17:25:16 +0200
commite15d6f9d8580b5f54376c2c48bd5ecf8ba0b5ce7 (patch)
tree1fa63bd3dbb0e1ddef8f3ccc9c9f170dcbcc2bc7
parent2d7d4800548e3b8ad3133b909aa9020954567640 (diff)
parenta8c9a0bd8167c99557c9d475631c844775883336 (diff)
downloadrust-e15d6f9d8580b5f54376c2c48bd5ecf8ba0b5ce7.tar.gz
rust-e15d6f9d8580b5f54376c2c48bd5ecf8ba0b5ce7.zip
Rollup merge of #123993 - compiler-errors:coroutine-obl, r=lcnr
Do `check_coroutine_obligations` once per typeck root

We only need to do `check_coroutine_obligations` once per typeck root, especially since the new solver can't really (easily) associate which obligations correspond to which coroutines.

This requires us to move the checks for sized coroutine fields into `mir_coroutine_witnesses`, but that's fine imo.

r? lcnr
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs47
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs13
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs11
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs40
-rw-r--r--compiler/rustc_span/src/source_map.rs2
-rw-r--r--tests/crashes/122552.rs10
-rw-r--r--tests/ui/coroutine/clone-impl.rs24
-rw-r--r--tests/ui/coroutine/clone-impl.stderr72
-rw-r--r--tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs10
-rw-r--r--tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr17
13 files changed, 148 insertions, 112 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index a43a67d50d8..32e1b19eaae 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -10,11 +10,10 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::Node;
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
-use rustc_infer::traits::{Obligation, TraitEngineExt as _};
+use rustc_infer::traits::Obligation;
 use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
 use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
-use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
@@ -24,10 +23,10 @@ use rustc_middle::ty::{
 };
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_target::abi::FieldIdx;
+use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _};
 use rustc_type_ir::fold::TypeFoldable;
 
 use std::cell::LazyCell;
@@ -1715,55 +1714,31 @@ fn opaque_type_cycle_error(
     err.emit()
 }
 
-// FIXME(@lcnr): This should not be computed per coroutine, but instead once for
-// each typeck root.
 pub(super) fn check_coroutine_obligations(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
 ) -> Result<(), ErrorGuaranteed> {
-    debug_assert!(tcx.is_coroutine(def_id.to_def_id()));
+    debug_assert!(!tcx.is_typeck_child(def_id.to_def_id()));
 
-    let typeck = tcx.typeck(def_id);
-    let param_env = tcx.param_env(typeck.hir_owner.def_id);
+    let typeck_results = tcx.typeck(def_id);
+    let param_env = tcx.param_env(def_id);
 
-    let coroutine_interior_predicates = &typeck.coroutine_interior_predicates[&def_id];
-    debug!(?coroutine_interior_predicates);
+    debug!(?typeck_results.coroutine_stalled_predicates);
 
     let infcx = tcx
         .infer_ctxt()
         // typeck writeback gives us predicates with their regions erased.
         // As borrowck already has checked lifetimes, we do not need to do it again.
         .ignoring_regions()
-        // Bind opaque types to type checking root, as they should have been checked by borrowck,
-        // but may show up in some cases, like when (root) obligations are stalled in the new solver.
-        .with_opaque_type_inference(typeck.hir_owner.def_id)
+        .with_opaque_type_inference(def_id)
         .build();
 
-    let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
-    for (predicate, cause) in coroutine_interior_predicates {
-        let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
-        fulfillment_cx.register_predicate_obligation(&infcx, obligation);
-    }
-
-    if (tcx.features().unsized_locals || tcx.features().unsized_fn_params)
-        && let Some(coroutine) = tcx.mir_coroutine_witnesses(def_id)
-    {
-        for field_ty in coroutine.field_tys.iter() {
-            fulfillment_cx.register_bound(
-                &infcx,
-                param_env,
-                field_ty.ty,
-                tcx.require_lang_item(hir::LangItem::Sized, Some(field_ty.source_info.span)),
-                ObligationCause::new(
-                    field_ty.source_info.span,
-                    def_id,
-                    ObligationCauseCode::SizedCoroutineInterior(def_id),
-                ),
-            );
-        }
+    let ocx = ObligationCtxt::new(&infcx);
+    for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
+        ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
     }
 
-    let errors = fulfillment_cx.select_all_or_error(&infcx);
+    let errors = ocx.select_all_or_error();
     debug!(?errors);
     if !errors.is_empty() {
         return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 0b684fdf57b..0ba5d187864 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -588,12 +588,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             obligations
                 .extend(self.fulfillment_cx.borrow_mut().drain_unstalled_obligations(&self.infcx));
 
-            let obligations = obligations.into_iter().map(|o| (o.predicate, o.cause)).collect();
-            debug!(?obligations);
-            self.typeck_results
-                .borrow_mut()
-                .coroutine_interior_predicates
-                .insert(expr_def_id, obligations);
+            let obligations = obligations.into_iter().map(|o| (o.predicate, o.cause));
+            self.typeck_results.borrow_mut().coroutine_stalled_predicates.extend(obligations);
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 43e5ab0ed53..133778a416c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -23,7 +23,7 @@ use rustc_hir::{
 };
 use rustc_hir_analysis::collect::suggest_impl_trait;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::traits::{self};
+use rustc_infer::traits;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::print::with_no_trimmed_paths;
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 875f8b23a84..0a40ffb0d5a 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -551,15 +551,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn visit_coroutine_interior(&mut self) {
         let fcx_typeck_results = self.fcx.typeck_results.borrow();
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
-        self.tcx().with_stable_hashing_context(move |ref hcx| {
-            for (&expr_def_id, predicates) in
-                fcx_typeck_results.coroutine_interior_predicates.to_sorted(hcx, false).into_iter()
-            {
-                let predicates =
-                    self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id));
-                self.typeck_results.coroutine_interior_predicates.insert(expr_def_id, predicates);
-            }
-        })
+        for (predicate, cause) in &fcx_typeck_results.coroutine_stalled_predicates {
+            let (predicate, cause) = self.resolve((*predicate, cause.clone()), &cause.span);
+            self.typeck_results.coroutine_stalled_predicates.insert((predicate, cause));
+        }
     }
 
     #[instrument(skip(self), level = "debug")]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 91cef02c7d1..b593c41a8ea 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -759,7 +759,9 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
     tcx.hir().par_body_owners(|def_id| {
         if tcx.is_coroutine(def_id.to_def_id()) {
             tcx.ensure().mir_coroutine_witnesses(def_id);
-            tcx.ensure().check_coroutine_obligations(def_id);
+            tcx.ensure().check_coroutine_obligations(
+                tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
+            );
         }
     });
     sess.time("layout_testing", || layout_test::test_layout(tcx));
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 25bca70f102..0c4409197bb 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -7,10 +7,8 @@ use crate::{
         GenericArgs, GenericArgsRef, Ty, UserArgs,
     },
 };
-use rustc_data_structures::{
-    fx::FxIndexMap,
-    unord::{ExtendUnord, UnordItems, UnordSet},
-};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::{
     self as hir,
@@ -201,8 +199,7 @@ pub struct TypeckResults<'tcx> {
 
     /// Stores the predicates that apply on coroutine witness types.
     /// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
-    pub coroutine_interior_predicates:
-        LocalDefIdMap<Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
+    pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
 
     /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
     /// as `&[u8]`, depending on the pattern in which they are used.
@@ -243,7 +240,7 @@ impl<'tcx> TypeckResults<'tcx> {
             closure_min_captures: Default::default(),
             closure_fake_reads: Default::default(),
             rvalue_scopes: Default::default(),
-            coroutine_interior_predicates: Default::default(),
+            coroutine_stalled_predicates: Default::default(),
             treat_byte_string_as_slice: Default::default(),
             closure_size_eval: Default::default(),
             offset_of_data: Default::default(),
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index e2a911f0dc7..b745d97567d 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -80,6 +80,10 @@ use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_target::spec::PanicStrategy;
+use rustc_trait_selection::infer::TyCtxtInferExt as _;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::ObligationCtxt;
+use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
 use std::{iter, ops};
 
 pub struct StateTransform;
@@ -1584,10 +1588,46 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>(
     let (_, coroutine_layout, _) = compute_layout(liveness_info, body);
 
     check_suspend_tys(tcx, &coroutine_layout, body);
+    check_field_tys_sized(tcx, &coroutine_layout, def_id);
 
     Some(coroutine_layout)
 }
 
+fn check_field_tys_sized<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    coroutine_layout: &CoroutineLayout<'tcx>,
+    def_id: LocalDefId,
+) {
+    // No need to check if unsized_locals/unsized_fn_params is disabled,
+    // since we will error during typeck.
+    if !tcx.features().unsized_locals && !tcx.features().unsized_fn_params {
+        return;
+    }
+
+    let infcx = tcx.infer_ctxt().ignoring_regions().build();
+    let param_env = tcx.param_env(def_id);
+
+    let ocx = ObligationCtxt::new(&infcx);
+    for field_ty in &coroutine_layout.field_tys {
+        ocx.register_bound(
+            ObligationCause::new(
+                field_ty.source_info.span,
+                def_id,
+                ObligationCauseCode::SizedCoroutineInterior(def_id),
+            ),
+            param_env,
+            field_ty.ty,
+            tcx.require_lang_item(hir::LangItem::Sized, Some(field_ty.source_info.span)),
+        );
+    }
+
+    let errors = ocx.select_all_or_error();
+    debug!(?errors);
+    if !errors.is_empty() {
+        infcx.err_ctxt().report_fulfillment_errors(errors);
+    }
+}
+
 impl<'tcx> MirPass<'tcx> for StateTransform {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let Some(old_yield_ty) = body.yield_ty() else {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index e3e76caebaf..33bd11cc807 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, R
 use rustc_data_structures::unhash::UnhashMap;
 use std::fs;
 use std::io::{self, BorrowedBuf, Read};
-use std::path::{self};
+use std::path;
 
 #[cfg(test)]
 mod tests;
diff --git a/tests/crashes/122552.rs b/tests/crashes/122552.rs
deleted file mode 100644
index 29566941e22..00000000000
--- a/tests/crashes/122552.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ known-bug: #122552
-//@ edition:2021
-
-trait X {
-    fn line_stream<'a, Repr>() -> Self::LineStreamFut<{ async {} }, Repr>;
-}
-
-struct Y;
-
-pub fn main() {}
diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs
index eed6f851bd0..fffdae632ef 100644
--- a/tests/ui/coroutine/clone-impl.rs
+++ b/tests/ui/coroutine/clone-impl.rs
@@ -6,18 +6,18 @@
 
 struct NonClone;
 
-fn main() {
+fn test1() {
     let copyable: u32 = 123;
-    let clonable_0: Vec<u32> = Vec::new();
-    let clonable_1: Vec<u32> = Vec::new();
-    let non_clonable: NonClone = NonClone;
-
     let gen_copy_0 = move || {
         yield;
         drop(copyable);
     };
     check_copy(&gen_copy_0);
     check_clone(&gen_copy_0);
+}
+
+fn test2() {
+    let copyable: u32 = 123;
     let gen_copy_1 = move || {
         /*
         let v = vec!['a'];
@@ -33,6 +33,10 @@ fn main() {
     };
     check_copy(&gen_copy_1);
     check_clone(&gen_copy_1);
+}
+
+fn test3() {
+    let clonable_0: Vec<u32> = Vec::new();
     let gen_clone_0 = move || {
         let v = vec!['a'];
         yield;
@@ -43,6 +47,10 @@ fn main() {
     //~^ ERROR the trait bound `Vec<u32>: Copy` is not satisfied
     //~| ERROR the trait bound `Vec<char>: Copy` is not satisfied
     check_clone(&gen_clone_0);
+}
+
+fn test4() {
+    let clonable_1: Vec<u32> = Vec::new();
     let gen_clone_1 = move || {
         let v = vec!['a'];
         /*
@@ -59,6 +67,10 @@ fn main() {
     //~^ ERROR the trait bound `Vec<u32>: Copy` is not satisfied
     //~| ERROR the trait bound `Vec<char>: Copy` is not satisfied
     check_clone(&gen_clone_1);
+}
+
+fn test5() {
+    let non_clonable: NonClone = NonClone;
     let gen_non_clone = move || {
         yield;
         drop(non_clonable);
@@ -71,3 +83,5 @@ fn main() {
 
 fn check_copy<T: Copy>(_x: &T) {}
 fn check_clone<T: Clone>(_x: &T) {}
+
+fn main() {}
diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr
index 1d4804501d8..b454846faac 100644
--- a/tests/ui/coroutine/clone-impl.stderr
+++ b/tests/ui/coroutine/clone-impl.stderr
@@ -1,76 +1,76 @@
-error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
-  --> $DIR/clone-impl.rs:42:5
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
+  --> $DIR/clone-impl.rs:46:5
    |
 LL |     let gen_clone_0 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:40:14
+  --> $DIR/clone-impl.rs:44: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:72:18
+  --> $DIR/clone-impl.rs:84:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
-  --> $DIR/clone-impl.rs:42:5
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
+  --> $DIR/clone-impl.rs:46:5
    |
 LL |     let gen_clone_0 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
-  --> $DIR/clone-impl.rs:38:9
+  --> $DIR/clone-impl.rs:42: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:72:18
+  --> $DIR/clone-impl.rs:84: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:46:23: 46:30}`
-  --> $DIR/clone-impl.rs:58:5
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
+  --> $DIR/clone-impl.rs:66:5
    |
 LL |     let gen_clone_1 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:56:14
+  --> $DIR/clone-impl.rs:64: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:72:18
+  --> $DIR/clone-impl.rs:84:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
-  --> $DIR/clone-impl.rs:58:5
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
+  --> $DIR/clone-impl.rs:66:5
    |
 LL |     let gen_clone_1 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
-  --> $DIR/clone-impl.rs:52:9
+  --> $DIR/clone-impl.rs:60:9
    |
 LL |         let v = vec!['a'];
    |             - has type `Vec<char>` which does not implement `Copy`
@@ -78,27 +78,27 @@ LL |         let v = vec!['a'];
 LL |         yield;
    |         ^^^^^ yield occurs here, with `v` maybe used later
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:72:18
+  --> $DIR/clone-impl.rs:84: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:62:25: 62:32}`
-  --> $DIR/clone-impl.rs:66:5
+error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
+  --> $DIR/clone-impl.rs:78:5
    |
 LL |     let gen_non_clone = move || {
-   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
+   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
 ...
 LL |     check_copy(&gen_non_clone);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:64:14
+  --> $DIR/clone-impl.rs:76: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:72:18
+  --> $DIR/clone-impl.rs:84:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -108,22 +108,22 @@ LL + #[derive(Copy)]
 LL | struct NonClone;
    |
 
-error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
-  --> $DIR/clone-impl.rs:68:5
+error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
+  --> $DIR/clone-impl.rs:80:5
    |
 LL |     let gen_non_clone = move || {
-   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
+   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
 ...
 LL |     check_clone(&gen_non_clone);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}: Clone`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Clone`
    |
 note: captured value does not implement `Clone`
-  --> $DIR/clone-impl.rs:64:14
+  --> $DIR/clone-impl.rs:76: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:73:19
+  --> $DIR/clone-impl.rs:85:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
diff --git a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
new file mode 100644
index 00000000000..07c13239a2c
--- /dev/null
+++ b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
@@ -0,0 +1,10 @@
+//@ edition:2021
+
+trait X {
+    fn test() -> Self::Assoc<{ async {} }>;
+    //~^ ERROR associated type `Assoc` not found for `Self`
+    //~| ERROR associated type `Assoc` not found for `Self`
+
+}
+
+pub fn main() {}
diff --git a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
new file mode 100644
index 00000000000..864c6556d79
--- /dev/null
+++ b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
@@ -0,0 +1,17 @@
+error[E0220]: associated type `Assoc` not found for `Self`
+  --> $DIR/coroutine-in-orphaned-anon-const.rs:4:24
+   |
+LL |     fn test() -> Self::Assoc<{ async {} }>;
+   |                        ^^^^^ associated type `Assoc` not found
+
+error[E0220]: associated type `Assoc` not found for `Self`
+  --> $DIR/coroutine-in-orphaned-anon-const.rs:4:24
+   |
+LL |     fn test() -> Self::Assoc<{ async {} }>;
+   |                        ^^^^^ associated type `Assoc` not found
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0220`.