about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoshua Nelson <jnelson@cloudflare.com>2022-06-19 13:59:36 -0500
committerJoshua Nelson <jnelson@cloudflare.com>2022-06-19 15:31:22 -0500
commit1deca0425db3e74a61cb732e729c0777904e549c (patch)
tree0243373760ee6aa41c578a4d3a17dc9f026beb53
parentcdcc53b7dc002ea4a7a28105010c5a1126ee31b7 (diff)
downloadrust-1deca0425db3e74a61cb732e729c0777904e549c.tar.gz
rust-1deca0425db3e74a61cb732e729c0777904e549c.zip
Greatly improve error reporting for futures and generators in `note_obligation_cause_code`
Most futures don't go through this code path, because they're caught by
`maybe_note_obligation_cause_for_async_await`. But all generators do,
and `maybe_note` is imperfect and doesn't catch all futures. Improve the error message for those it misses.

At some point, we may want to consider unifying this with the code for `maybe_note_async_await`,
so that `async_await` notes all parent constraints, and `note_obligation` can point to yield points.
But both functions are quite complicated, and it's not clear to me how to combine them;
this seems like a good incremental improvement.
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs105
-rw-r--r--src/test/ui/async-await/issue-68112.stderr30
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr40
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.normal.stderr (renamed from src/test/ui/async-await/issue-70935-complex-spans.stderr)8
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.rs16
-rw-r--r--src/test/ui/async-await/partial-drop-partial-reinit.rs8
-rw-r--r--src/test/ui/async-await/partial-drop-partial-reinit.stderr20
-rw-r--r--src/test/ui/closures/closure-move-sync.stderr16
-rw-r--r--src/test/ui/generator/issue-68112.rs22
-rw-r--r--src/test/ui/generator/issue-68112.stderr41
-rw-r--r--src/test/ui/generator/not-send-sync.stderr11
-rw-r--r--src/test/ui/generator/print/generator-print-verbose-1.stderr33
-rw-r--r--src/test/ui/generator/print/generator-print-verbose-2.stderr11
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak2.rs18
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak2.stderr32
-rw-r--r--src/test/ui/interior-mutability/interior-mutability.stderr6
-rw-r--r--src/test/ui/kindck/kindck-nonsendable-1.stderr6
-rw-r--r--src/test/ui/no-send-res-ports.stderr11
-rw-r--r--src/test/ui/not-clone-closure.stderr9
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs8
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr10
21 files changed, 389 insertions, 72 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 09b73b982a0..159fcf932a1 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -8,6 +8,7 @@ use crate::infer::InferCtxt;
 use crate::traits::normalize_to;
 
 use hir::HirId;
+use rustc_ast::Movability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
@@ -2397,24 +2398,104 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     {
                         let parent_trait_ref =
                             self.resolve_vars_if_possible(data.parent_trait_pred);
-                        let ty = parent_trait_ref.skip_binder().self_ty();
-                        matches!(ty.kind(), ty::Generator(..))
-                            || matches!(ty.kind(), ty::Closure(..))
+                        let nested_ty = parent_trait_ref.skip_binder().self_ty();
+                        matches!(nested_ty.kind(), ty::Generator(..))
+                            || matches!(nested_ty.kind(), ty::Closure(..))
                     } else {
                         false
                     }
                 };
 
+                let future_trait = self.tcx.lang_items().future_trait().unwrap();
+                let opaque_ty_is_future = |def_id| {
+                    self.tcx.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
+                        if let ty::PredicateKind::Trait(trait_predicate) =
+                            predicate.kind().skip_binder()
+                        {
+                            trait_predicate.trait_ref.def_id == future_trait
+                        } else {
+                            false
+                        }
+                    })
+                };
+
+                let from_generator = tcx.lang_items().from_generator_fn().unwrap();
+
                 // Don't print the tuple of capture types
-                if !is_upvar_tys_infer_tuple {
-                    let msg = format!("required because it appears within the type `{}`", ty);
-                    match ty.kind() {
-                        ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
-                            Some(ident) => err.span_note(ident.span, &msg),
-                            None => err.note(&msg),
-                        },
-                        _ => err.note(&msg),
-                    };
+                'print: {
+                    if !is_upvar_tys_infer_tuple {
+                        let msg = format!("required because it appears within the type `{}`", ty);
+                        match ty.kind() {
+                            ty::Adt(def, _) => {
+                                // `gen_future` is used in all async functions; it doesn't add any additional info.
+                                if self.tcx.is_diagnostic_item(sym::gen_future, def.did()) {
+                                    break 'print;
+                                }
+                                match self.tcx.opt_item_ident(def.did()) {
+                                    Some(ident) => err.span_note(ident.span, &msg),
+                                    None => err.note(&msg),
+                                }
+                            }
+                            ty::Opaque(def_id, _) => {
+                                // Avoid printing the future from `core::future::from_generator`, it's not helpful
+                                if tcx.parent(*def_id) == from_generator {
+                                    break 'print;
+                                }
+
+                                // If the previous type is `from_generator`, this is the future generated by the body of an async function.
+                                // Avoid printing it twice (it was already printed in the `ty::Generator` arm below).
+                                let is_future = opaque_ty_is_future(def_id);
+                                debug!(
+                                    ?obligated_types,
+                                    ?is_future,
+                                    "note_obligation_cause_code: check for async fn"
+                                );
+                                if opaque_ty_is_future(def_id)
+                                    && obligated_types.last().map_or(false, |ty| match ty.kind() {
+                                        ty::Opaque(last_def_id, _) => {
+                                            tcx.parent(*last_def_id) == from_generator
+                                        }
+                                        _ => false,
+                                    })
+                                {
+                                    break 'print;
+                                }
+                                err.span_note(self.tcx.def_span(def_id), &msg)
+                            }
+                            ty::GeneratorWitness(bound_tys) => {
+                                use std::fmt::Write;
+
+                                // FIXME: this is kind of an unusual format for rustc, can we make it more clear?
+                                // Maybe we should just remove this note altogether?
+                                // FIXME: only print types which don't meet the trait requirement
+                                let mut msg =
+                                    "required because it captures the following types: ".to_owned();
+                                for ty in bound_tys.skip_binder() {
+                                    write!(msg, "`{}`, ", ty).unwrap();
+                                }
+                                err.note(msg.trim_end_matches(", "))
+                            }
+                            ty::Generator(def_id, _, movability) => {
+                                let sp = self.tcx.def_span(def_id);
+
+                                // Special-case this to say "async block" instead of `[static generator]`.
+                                let kind = if *movability == Movability::Static {
+                                    "async block"
+                                } else {
+                                    "generator"
+                                };
+                                err.span_note(
+                                    sp,
+                                    &format!("required because it's used within this {}", kind),
+                                )
+                            }
+                            ty::Closure(def_id, _) => err.span_note(
+                                self.tcx.def_span(def_id),
+                                &format!("required because it's used within this closure"),
+                            ),
+                            _ => err.note(&msg),
+                        };
+                    }
                 }
 
                 obligated_types.push(ty);
diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr
index 28d94b14ac9..b8d3e1540d8 100644
--- a/src/test/ui/async-await/issue-68112.stderr
+++ b/src/test/ui/async-await/issue-68112.stderr
@@ -42,15 +42,27 @@ LL |     require_send(send_fut);
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
-   = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]`
-   = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
-   = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
-   = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
-   = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
-   = note: required because it appears within the type `{ResumeTy, impl Future<Output = Arc<RefCell<i32>>>, (), i32, Ready<i32>}`
-   = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]`
-   = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
-   = note: required because it appears within the type `impl Future<Output = ()>`
+note: required because it's used within this async block
+  --> $DIR/issue-68112.rs:47:31
+   |
+LL | async fn ready2<T>(t: T) -> T { t }
+   |                               ^^^^^
+note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
+  --> $DIR/issue-68112.rs:48:31
+   |
+LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
+note: required because it's used within this async block
+  --> $DIR/issue-68112.rs:55:26
+   |
+LL |       let send_fut = async {
+   |  __________________________^
+LL | |         let non_send_fut = make_non_send_future2();
+LL | |         let _ = non_send_fut.await;
+LL | |         ready(0).await;
+LL | |     };
+   | |_____^
 note: required by a bound in `require_send`
   --> $DIR/issue-68112.rs:11:25
    |
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
new file mode 100644
index 00000000000..19fd5eb7c73
--- /dev/null
+++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -0,0 +1,40 @@
+error[E0277]: `Sender<i32>` cannot be shared between threads safely
+  --> $DIR/issue-70935-complex-spans.rs:13:45
+   |
+LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
+   |                                             ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely
+   |
+   = help: the trait `Sync` is not implemented for `Sender<i32>`
+   = note: required because of the requirements on the impl of `Send` for `&Sender<i32>`
+note: required because it's used within this closure
+  --> $DIR/issue-70935-complex-spans.rs:25:13
+   |
+LL |           baz(|| async{
+   |  _____________^
+LL | |             foo(tx.clone());
+LL | |         }).await;
+   | |_________^
+note: required because it's used within this async block
+  --> $DIR/issue-70935-complex-spans.rs:9:67
+   |
+LL |   async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
+   |  ___________________________________________________________________^
+LL | |
+LL | | }
+   | |_^
+   = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
+note: required because it's used within this async block
+  --> $DIR/issue-70935-complex-spans.rs:23:16
+   |
+LL |       async move {
+   |  ________________^
+LL | |
+LL | |         baz(|| async{
+LL | |             foo(tx.clone());
+LL | |         }).await;
+LL | |     }
+   | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr
index db309938119..2174f260a71 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.stderr
+++ b/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr
@@ -1,12 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-70935-complex-spans.rs:10:45
+  --> $DIR/issue-70935-complex-spans.rs:13:45
    |
 LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
    |                                             ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `Sender<i32>`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/issue-70935-complex-spans.rs:15:11
+  --> $DIR/issue-70935-complex-spans.rs:27:11
    |
 LL |           baz(|| async{
    |  _____________-
@@ -14,9 +14,9 @@ LL | |             foo(tx.clone());
 LL | |         }).await;
    | |         - ^^^^^^ await occurs here, with the value maybe used later
    | |_________|
-   |           has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10]` which is not `Send`
+   |           has type `[closure@$DIR/issue-70935-complex-spans.rs:25:13: 27:10]` which is not `Send`
 note: the value is later dropped here
-  --> $DIR/issue-70935-complex-spans.rs:15:17
+  --> $DIR/issue-70935-complex-spans.rs:27:17
    |
 LL |         }).await;
    |                 ^
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.rs b/src/test/ui/async-await/issue-70935-complex-spans.rs
index 2965a7e0654..4bf94fe342c 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.rs
+++ b/src/test/ui/async-await/issue-70935-complex-spans.rs
@@ -1,16 +1,28 @@
 // edition:2018
+// revisions: normal drop_tracking
+// [drop_tracking]compile-flags:-Zdrop-tracking
 // #70935: Check if we do not emit snippet
 // with newlines which lead complex diagnostics.
 
 use std::future::Future;
 
 async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
+//[drop_tracking]~^ within this async block
 }
 
 fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
-    //~^ ERROR: future cannot be sent between threads safely
+    //[normal]~^ ERROR: future cannot be sent between threads safely
+    //[drop_tracking]~^^ ERROR: `Sender<i32>` cannot be shared
+    //[drop_tracking]~|  NOTE: cannot be shared
+    //[drop_tracking]~|  NOTE: requirements on the impl of `Send`
+    //[drop_tracking]~|  NOTE: captures the following types
+    //[drop_tracking]~|  NOTE: in this expansion
+    //[drop_tracking]~|  NOTE: in this expansion
+    //[drop_tracking]~|  NOTE: in this expansion
+    //[drop_tracking]~|  NOTE: in this expansion
     async move {
-        baz(|| async{
+    //[drop_tracking]~^ within this async block
+        baz(|| async{ //[drop_tracking]~ NOTE: used within this closure
             foo(tx.clone());
         }).await;
     }
diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.rs b/src/test/ui/async-await/partial-drop-partial-reinit.rs
index 73f0ca8153c..4fcfacea3f8 100644
--- a/src/test/ui/async-await/partial-drop-partial-reinit.rs
+++ b/src/test/ui/async-await/partial-drop-partial-reinit.rs
@@ -5,9 +5,15 @@
 fn main() {
     gimme_send(foo());
     //~^ ERROR cannot be sent between threads safely
+    //~| NOTE cannot be sent
+    //~| NOTE bound introduced by
+    //~| NOTE appears within the type
+    //~| NOTE captures the following types
 }
 
 fn gimme_send<T: Send>(t: T) {
+//~^ NOTE required by this bound
+//~| NOTE required by a bound
     drop(t);
 }
 
@@ -20,6 +26,8 @@ impl Drop for NotSend {
 impl !Send for NotSend {}
 
 async fn foo() {
+//~^ NOTE used within this async block
+//~| NOTE within this `impl Future
     let mut x = (NotSend {},);
     drop(x.0);
     x.0 = NotSend {};
diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.stderr
index a1c4957e984..96d0c71f103 100644
--- a/src/test/ui/async-await/partial-drop-partial-reinit.stderr
+++ b/src/test/ui/async-await/partial-drop-partial-reinit.stderr
@@ -11,13 +11,21 @@ LL | async fn foo() {
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
    = note: required because it appears within the type `(NotSend,)`
-   = note: required because it appears within the type `{ResumeTy, (NotSend,), impl Future<Output = ()>, ()}`
-   = note: required because it appears within the type `[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]`
-   = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>`
-   = note: required because it appears within the type `impl Future<Output = ()>`
-   = note: required because it appears within the type `impl Future<Output = ()>`
+   = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future<Output = ()>`, `()`
+note: required because it's used within this async block
+  --> $DIR/partial-drop-partial-reinit.rs:28:16
+   |
+LL |   async fn foo() {
+   |  ________________^
+LL | |
+LL | |
+LL | |     let mut x = (NotSend {},);
+...  |
+LL | |     bar().await;
+LL | | }
+   | |_^
 note: required by a bound in `gimme_send`
-  --> $DIR/partial-drop-partial-reinit.rs:10:18
+  --> $DIR/partial-drop-partial-reinit.rs:14:18
    |
 LL | fn gimme_send<T: Send>(t: T) {
    |                  ^^^^ required by this bound in `gimme_send`
diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr
index 618c9a17247..cbc4e2e5231 100644
--- a/src/test/ui/closures/closure-move-sync.stderr
+++ b/src/test/ui/closures/closure-move-sync.stderr
@@ -6,7 +6,15 @@ LL |     let t = thread::spawn(|| {
    |
    = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>`
    = note: required because of the requirements on the impl of `Send` for `&std::sync::mpsc::Receiver<()>`
-   = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:6:27: 9:6]`
+note: required because it's used within this closure
+  --> $DIR/closure-move-sync.rs:6:27
+   |
+LL |       let t = thread::spawn(|| {
+   |  ___________________________^
+LL | |         recv.recv().unwrap();
+LL | |
+LL | |     });
+   | |_____^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
    |
@@ -21,7 +29,11 @@ LL |     thread::spawn(|| tx.send(()).unwrap());
    |
    = help: the trait `Sync` is not implemented for `Sender<()>`
    = note: required because of the requirements on the impl of `Send` for `&Sender<()>`
-   = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:18:19: 18:42]`
+note: required because it's used within this closure
+  --> $DIR/closure-move-sync.rs:18:19
+   |
+LL |     thread::spawn(|| tx.send(()).unwrap());
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
    |
diff --git a/src/test/ui/generator/issue-68112.rs b/src/test/ui/generator/issue-68112.rs
index feb07c9bf88..3fcef773b68 100644
--- a/src/test/ui/generator/issue-68112.rs
+++ b/src/test/ui/generator/issue-68112.rs
@@ -20,6 +20,10 @@ pub fn make_gen1<T>(t: T) -> Ready<T> {
 }
 
 fn require_send(_: impl Send) {}
+//~^ NOTE required by a bound
+//~| NOTE required by a bound
+//~| NOTE required by this bound
+//~| NOTE required by this bound
 
 fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> {
     make_gen1(Arc::new(RefCell::new(0)))
@@ -28,29 +32,39 @@ fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> {
 fn test1() {
     let send_gen = || {
         let _non_send_gen = make_non_send_generator();
+        //~^ NOTE not `Send`
         yield;
-    };
+        //~^ NOTE yield occurs here
+        //~| NOTE value is used across a yield
+    }; //~ NOTE later dropped here
     require_send(send_gen);
     //~^ ERROR generator cannot be sent between threads
+    //~| NOTE not `Send`
 }
 
 pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
-    || {
+//~^ NOTE appears within the type
+//~| NOTE expansion of desugaring
+    || { //~ NOTE used within this generator
         yield;
         t
     }
 }
-fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> { //~ NOTE appears within the type
+//~^ NOTE expansion of desugaring
     make_gen2(Arc::new(RefCell::new(0)))
 }
 
 fn test2() {
-    let send_gen = || {
+    let send_gen = || { //~ NOTE used within this generator
         let _non_send_gen = make_non_send_generator2();
         yield;
     };
     require_send(send_gen);
     //~^ ERROR `RefCell<i32>` cannot be shared between threads safely
+    //~| NOTE `RefCell<i32>` cannot be shared between threads safely
+    //~| NOTE requirements on the impl
+    //~| NOTE captures the following types
 }
 
 fn main() {}
diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr
index a7d7a732548..83f068c2076 100644
--- a/src/test/ui/generator/issue-68112.stderr
+++ b/src/test/ui/generator/issue-68112.stderr
@@ -1,17 +1,19 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-68112.rs:33:5
+  --> $DIR/issue-68112.rs:40:5
    |
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^ generator is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/issue-68112.rs:31:9
+  --> $DIR/issue-68112.rs:36:9
    |
 LL |         let _non_send_gen = make_non_send_generator();
    |             ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send`
+LL |
 LL |         yield;
    |         ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
+...
 LL |     };
    |     - `_non_send_gen` is later dropped here
 note: required by a bound in `require_send`
@@ -21,18 +23,41 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error[E0277]: `RefCell<i32>` cannot be shared between threads safely
-  --> $DIR/issue-68112.rs:52:5
+  --> $DIR/issue-68112.rs:63:5
    |
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
-   = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6]`
-   = note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
-   = note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
-   = note: required because it appears within the type `{impl Generator<Return = Arc<RefCell<i32>>>, ()}`
-   = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]`
+note: required because it's used within this generator
+  --> $DIR/issue-68112.rs:48:5
+   |
+LL | /     || {
+LL | |         yield;
+LL | |         t
+LL | |     }
+   | |_____^
+note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+  --> $DIR/issue-68112.rs:45:30
+   |
+LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+  --> $DIR/issue-68112.rs:53:34
+   |
+LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: required because it captures the following types: `impl Generator<Return = Arc<RefCell<i32>>>`, `()`
+note: required because it's used within this generator
+  --> $DIR/issue-68112.rs:59:20
+   |
+LL |       let send_gen = || {
+   |  ____________________^
+LL | |         let _non_send_gen = make_non_send_generator2();
+LL | |         yield;
+LL | |     };
+   | |_____^
 note: required by a bound in `require_send`
   --> $DIR/issue-68112.rs:22:25
    |
diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr
index 4d2faa198f1..edf9ee628a2 100644
--- a/src/test/ui/generator/not-send-sync.stderr
+++ b/src/test/ui/generator/not-send-sync.stderr
@@ -6,7 +6,16 @@ LL |     assert_send(|| {
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: required because of the requirements on the impl of `Send` for `&Cell<i32>`
-   = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6]`
+note: required because it's used within this generator
+  --> $DIR/not-send-sync.rs:16:17
+   |
+LL |       assert_send(|| {
+   |  _________________^
+LL | |
+LL | |         drop(&a);
+LL | |         yield;
+LL | |     });
+   | |_____^
 note: required by a bound in `assert_send`
   --> $DIR/not-send-sync.rs:7:23
    |
diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr
index 2f7faf520d9..3ee4c1458ba 100644
--- a/src/test/ui/generator/print/generator-print-verbose-1.stderr
+++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr
@@ -28,11 +28,34 @@ LL |     require_send(send_gen);
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
-   = note: required because it appears within the type `[make_gen2<Arc<RefCell<i32>>>::{closure#0} upvar_tys=(Arc<RefCell<i32>>) {()}]`
-   = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
-   = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
-   = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), []), ()}`
-   = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), []), ()}]`
+note: required because it's used within this generator
+  --> $DIR/generator-print-verbose-1.rs:42:5
+   |
+LL | /     || {
+LL | |         yield;
+LL | |         t
+LL | |     }
+   | |_____^
+note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
+  --> $DIR/generator-print-verbose-1.rs:41:30
+   |
+LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
+  --> $DIR/generator-print-verbose-1.rs:47:34
+   |
+LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: required because it captures the following types: `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()`
+note: required because it's used within this generator
+  --> $DIR/generator-print-verbose-1.rs:52:20
+   |
+LL |       let send_gen = || {
+   |  ____________________^
+LL | |         let _non_send_gen = make_non_send_generator2();
+LL | |         yield;
+LL | |     };
+   | |_____^
 note: required by a bound in `require_send`
   --> $DIR/generator-print-verbose-1.rs:26:25
    |
diff --git a/src/test/ui/generator/print/generator-print-verbose-2.stderr b/src/test/ui/generator/print/generator-print-verbose-2.stderr
index fb2a5754dd3..1356fa5f152 100644
--- a/src/test/ui/generator/print/generator-print-verbose-2.stderr
+++ b/src/test/ui/generator/print/generator-print-verbose-2.stderr
@@ -6,7 +6,16 @@ LL |     assert_send(|| {
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: required because of the requirements on the impl of `Send` for `&'_#4r Cell<i32>`
-   = note: required because it appears within the type `[main::{closure#1} upvar_tys=(&'_#4r Cell<i32>) _#17t]`
+note: required because it's used within this generator
+  --> $DIR/generator-print-verbose-2.rs:19:17
+   |
+LL |       assert_send(|| {
+   |  _________________^
+LL | |
+LL | |         drop(&a);
+LL | |         yield;
+LL | |     });
+   | |_____^
 note: required by a bound in `assert_send`
   --> $DIR/generator-print-verbose-2.rs:10:23
    |
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.rs b/src/test/ui/impl-trait/auto-trait-leak2.rs
index a464f576dc7..09450089ada 100644
--- a/src/test/ui/impl-trait/auto-trait-leak2.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak2.rs
@@ -3,23 +3,37 @@ use std::rc::Rc;
 
 // Fast path, main can see the concrete type returned.
 fn before() -> impl Fn(i32) {
+//~^ NOTE within this `impl Fn
+//~| NOTE within the type `impl Fn
+//~| NOTE expansion of desugaring
     let p = Rc::new(Cell::new(0));
-    move |x| p.set(x)
+    move |x| p.set(x) //~ NOTE used within this closure
 }
 
 fn send<T: Send>(_: T) {}
+//~^ NOTE required by a bound
+//~| NOTE required by a bound
+//~| NOTE required by this bound
+//~| NOTE required by this bound
 
 fn main() {
     send(before());
     //~^ ERROR `Rc<Cell<i32>>` cannot be sent between threads safely
+    //~| NOTE `Rc<Cell<i32>>` cannot be sent between threads safely
+    //~| NOTE required by a bound
 
     send(after());
     //~^ ERROR `Rc<Cell<i32>>` cannot be sent between threads safely
+    //~| NOTE `Rc<Cell<i32>>` cannot be sent between threads safely
+    //~| NOTE required by a bound
 }
 
 // Deferred path, main has to wait until typeck finishes,
 // to check if the return type of after is Send.
 fn after() -> impl Fn(i32) {
+//~^ NOTE within this `impl Fn(i32)`
+//~| NOTE in this expansion
+//~| NOTE appears within the type
     let p = Rc::new(Cell::new(0));
-    move |x| p.set(x)
+    move |x| p.set(x) //~ NOTE used within this closure
 }
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr
index 37ae3c68029..d825843492d 100644
--- a/src/test/ui/impl-trait/auto-trait-leak2.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak2.rs:13:10
+  --> $DIR/auto-trait-leak2.rs:20:10
    |
 LL | fn before() -> impl Fn(i32) {
    |                ------------ within this `impl Fn(i32)`
@@ -10,16 +10,24 @@ LL |     send(before());
    |     required by a bound introduced by this call
    |
    = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
-   = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]`
-   = note: required because it appears within the type `impl Fn(i32)`
+note: required because it's used within this closure
+  --> $DIR/auto-trait-leak2.rs:10:5
+   |
+LL |     move |x| p.set(x)
+   |     ^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `impl Fn(i32)`
+  --> $DIR/auto-trait-leak2.rs:5:16
+   |
+LL | fn before() -> impl Fn(i32) {
+   |                ^^^^^^^^^^^^
 note: required by a bound in `send`
-  --> $DIR/auto-trait-leak2.rs:10:12
+  --> $DIR/auto-trait-leak2.rs:13:12
    |
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
 error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak2.rs:16:10
+  --> $DIR/auto-trait-leak2.rs:25:10
    |
 LL |     send(after());
    |     ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
@@ -30,10 +38,18 @@ LL | fn after() -> impl Fn(i32) {
    |               ------------ within this `impl Fn(i32)`
    |
    = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
-   = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22]`
-   = note: required because it appears within the type `impl Fn(i32)`
+note: required because it's used within this closure
+  --> $DIR/auto-trait-leak2.rs:38:5
+   |
+LL |     move |x| p.set(x)
+   |     ^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `impl Fn(i32)`
+  --> $DIR/auto-trait-leak2.rs:33:15
+   |
+LL | fn after() -> impl Fn(i32) {
+   |               ^^^^^^^^^^^^
 note: required by a bound in `send`
-  --> $DIR/auto-trait-leak2.rs:10:12
+  --> $DIR/auto-trait-leak2.rs:13:12
    |
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr
index cb22d5adb71..66fe3c74e2c 100644
--- a/src/test/ui/interior-mutability/interior-mutability.stderr
+++ b/src/test/ui/interior-mutability/interior-mutability.stderr
@@ -7,7 +7,11 @@ LL |     catch_unwind(|| { x.set(23); });
    = help: within `Cell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `Cell<i32>`
    = note: required because of the requirements on the impl of `UnwindSafe` for `&Cell<i32>`
-   = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:5:18: 5:35]`
+note: required because it's used within this closure
+  --> $DIR/interior-mutability.rs:5:18
+   |
+LL |     catch_unwind(|| { x.set(23); });
+   |                  ^^^^^^^^^^^^^^^^^
 note: required by a bound in `catch_unwind`
   --> $SRC_DIR/std/src/panic.rs:LL:COL
    |
diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr
index b3ebe7f5c7d..727573a0be4 100644
--- a/src/test/ui/kindck/kindck-nonsendable-1.stderr
+++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr
@@ -7,7 +7,11 @@ LL |     bar(move|| foo(x));
    |     `Rc<usize>` cannot be sent between threads safely
    |
    = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]`, the trait `Send` is not implemented for `Rc<usize>`
-   = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]`
+note: required because it's used within this closure
+  --> $DIR/kindck-nonsendable-1.rs:9:9
+   |
+LL |     bar(move|| foo(x));
+   |         ^^^^^^^^^^^^^
 note: required by a bound in `bar`
   --> $DIR/kindck-nonsendable-1.rs:5:21
    |
diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr
index 80708c989fc..e4c57c04e72 100644
--- a/src/test/ui/no-send-res-ports.stderr
+++ b/src/test/ui/no-send-res-ports.stderr
@@ -22,7 +22,16 @@ note: required because it appears within the type `Foo`
    |
 LL |     struct Foo {
    |            ^^^
-   = note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]`
+note: required because it's used within this closure
+  --> $DIR/no-send-res-ports.rs:25:19
+   |
+LL |       thread::spawn(move|| {
+   |  ___________________^
+LL | |
+LL | |         let y = x;
+LL | |         println!("{:?}", y);
+LL | |     });
+   | |_____^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
    |
diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr
index 78b35569c21..bebf561b120 100644
--- a/src/test/ui/not-clone-closure.stderr
+++ b/src/test/ui/not-clone-closure.stderr
@@ -10,7 +10,14 @@ LL |
 LL |       let hello = hello.clone();
    |                         ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`, the trait `Clone` is not implemented for `S`
    |
-   = note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`
+note: required because it's used within this closure
+  --> $DIR/not-clone-closure.rs:7:17
+   |
+LL |       let hello = move || {
+   |  _________________^
+LL | |         println!("Hello {}", a.0);
+LL | |     };
+   | |_____^
 help: consider annotating `S` with `#[derive(Clone)]`
    |
 LL | #[derive(Clone)]
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs
index 745379efa6d..fc89b0e870e 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs
@@ -4,7 +4,9 @@
 mod m {
     use std::rc::Rc;
 
-    type Foo = impl std::fmt::Debug;
+    type Foo = impl std::fmt::Debug; //~ NOTE appears within the type
+    //~^ within this `Foo`
+    //~| expansion of desugaring
 
     pub fn foo() -> Foo {
         Rc::new(22_u32)
@@ -12,8 +14,12 @@ mod m {
 }
 
 fn is_send<T: Send>(_: T) {}
+//~^ required by this bound
+//~| required by a bound
 
 fn main() {
     is_send(m::foo());
     //~^ ERROR: `Rc<u32>` cannot be sent between threads safely [E0277]
+    //~| NOTE cannot be sent
+    //~| NOTE required by a bound
 }
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
index 0664275b2ad..d7247302dd1 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Rc<u32>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leakage2.rs:17:13
+  --> $DIR/auto-trait-leakage2.rs:21:13
    |
 LL |     type Foo = impl std::fmt::Debug;
    |                -------------------- within this `Foo`
@@ -10,9 +10,13 @@ LL |     is_send(m::foo());
    |     required by a bound introduced by this call
    |
    = help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>`
-   = note: required because it appears within the type `Foo`
+note: required because it appears within the type `Foo`
+  --> $DIR/auto-trait-leakage2.rs:7:16
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `is_send`
-  --> $DIR/auto-trait-leakage2.rs:14:15
+  --> $DIR/auto-trait-leakage2.rs:16:15
    |
 LL | fn is_send<T: Send>(_: T) {}
    |               ^^^^ required by this bound in `is_send`