about summary refs log tree commit diff
path: root/src/test/ui/async-await
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 /src/test/ui/async-await
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.
Diffstat (limited to 'src/test/ui/async-await')
-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
6 files changed, 101 insertions, 21 deletions
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`