diff options
| author | bors <bors@rust-lang.org> | 2020-04-14 06:47:38 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-04-14 06:47:38 +0000 |
| commit | a3ef360368ac4c97883dc45287e752517e308f0e (patch) | |
| tree | 6ef048145715383fd1dbaa53a1e1f7fb1798f3c5 /src/test | |
| parent | 513a6473d69b3af34e6cdaa4efb288fe5283c3e9 (diff) | |
| parent | 4326d959f460321ed6f818a015f157af46ec5848 (diff) | |
| download | rust-a3ef360368ac4c97883dc45287e752517e308f0e.tar.gz rust-a3ef360368ac4c97883dc45287e752517e308f0e.zip | |
Auto merge of #70679 - tmandry:issue-68112, r=nikomatsakis
Improve async-await/generator obligation errors in some cases Fixes #68112. This change is best read one commit at a time (I add a test at the beginning and update it in each change after). The `test2` function is a case I found while writing the test that we don't handle with this code yet. I don't attempt to fix it in this PR, but it's a good candidate for future work. r? @davidtwco, @nikomatsakis
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/ui/async-await/async-fn-nonsend.stderr | 6 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-64130-1-sync.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-64130-2-send.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-64130-3-other.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-64130-4-async-move.stderr | 4 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-64130-non-send-future-diags.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-67252-unnamed-future.stderr | 4 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-68112.rs | 64 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-68112.stderr | 56 | ||||
| -rw-r--r-- | src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr | 4 | ||||
| -rw-r--r-- | src/test/ui/generator/issue-68112.rs | 56 | ||||
| -rw-r--r-- | src/test/ui/generator/issue-68112.stderr | 40 | ||||
| -rw-r--r-- | src/test/ui/generator/not-send-sync.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/generator/not-send-sync.stderr | 8 |
14 files changed, 234 insertions, 18 deletions
diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 04df6203e43..d36d59f1f68 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:24:5 | LL | let x = non_send(); - | - has type `impl std::fmt::Debug` + | - has type `impl std::fmt::Debug` which is not `Send` LL | drop(x); LL | fut().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later @@ -33,7 +33,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:33:20 | LL | match Some(non_send()) { - | ---------- has type `impl std::fmt::Debug` + | ---------- has type `impl std::fmt::Debug` which is not `Send` LL | Some(_) => fut().await, | ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later ... @@ -54,7 +54,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:42:9 | LL | let f: &mut std::fmt::Formatter = panic!(); - | - has type `&mut std::fmt::Formatter<'_>` + | - has type `&mut std::fmt::Formatter<'_>` which is not `Send` LL | if non_sync().fmt(f).unwrap() == () { LL | fut().await; | ^^^^^^^^^^^ await occurs here, with `f` maybe used later diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index b7a88c10e74..42e9e4642ce 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -12,7 +12,7 @@ note: future is not `Sync` as this value is used across an await --> $DIR/issue-64130-1-sync.rs:15:5 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which is not `Sync` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index ec183088771..f6f834618d3 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-2-send.rs:15:5 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which is not `Send` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 6b40cc9184d..3475b66b375 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -16,7 +16,7 @@ note: future does not implement `Qux` as this value is used across an await --> $DIR/issue-64130-3-other.rs:18:5 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which does not implement `Qux` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 1e52d74f155..fc231d394c1 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -2,7 +2,7 @@ error: future cannot be sent between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` ... LL | / async move { LL | | match client.status() { @@ -18,7 +18,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-4-async-move.rs:21:26 | LL | match client.status() { - | ------ has type `&Client` + | ------ has type `&Client` which is not `Send` LL | 200 => { LL | let _x = get().await; | ^^^^^^^^^^^ await occurs here, with `client` maybe used later diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 0f4441edb13..f72757339cc 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-non-send-future-diags.rs:15:5 | LL | let g = x.lock().unwrap(); - | - has type `std::sync::MutexGuard<'_, u32>` + | - has type `std::sync::MutexGuard<'_, u32>` which is not `Send` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `g` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr index cbcc3cf5d78..b43478ee207 100644 --- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr +++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr @@ -5,14 +5,14 @@ LL | fn spawn<T: Send>(_: T) {} | ---- required by this bound in `spawn` ... LL | spawn(async { - | ^^^^^ future is not `Send` + | ^^^^^ future created by async block is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*mut ()` note: future is not `Send` as this value is used across an await --> $DIR/issue-67252-unnamed-future.rs:20:9 | LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` - | -- has type `*mut ()` + | -- has type `*mut ()` which is not `Send` LL | AFuture.await; | ^^^^^^^^^^^^^ await occurs here, with `_a` maybe used later LL | }); diff --git a/src/test/ui/async-await/issue-68112.rs b/src/test/ui/async-await/issue-68112.rs new file mode 100644 index 00000000000..11b17836808 --- /dev/null +++ b/src/test/ui/async-await/issue-68112.rs @@ -0,0 +1,64 @@ +// edition:2018 + +use std::{ + future::Future, + cell::RefCell, + sync::Arc, + pin::Pin, + task::{Context, Poll}, +}; + +fn require_send(_: impl Send) {} + +struct Ready<T>(Option<T>); +impl<T> Future for Ready<T> { + type Output = T; + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> { + Poll::Ready(self.0.take().unwrap()) + } +} +fn ready<T>(t: T) -> Ready<T> { + Ready(Some(t)) +} + +fn make_non_send_future1() -> impl Future<Output = Arc<RefCell<i32>>> { + ready(Arc::new(RefCell::new(0))) +} + +fn test1() { + let send_fut = async { + let non_send_fut = make_non_send_future1(); + let _ = non_send_fut.await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR future cannot be sent between threads +} + +fn test1_no_let() { + let send_fut = async { + let _ = make_non_send_future1().await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR future cannot be sent between threads +} + +async fn ready2<T>(t: T) -> T { t } +fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> { + ready2(Arc::new(RefCell::new(0))) +} + +// Ideally this test would have diagnostics similar to the test above, but right +// now it doesn't. +fn test2() { + let send_fut = async { + let non_send_fut = make_non_send_future2(); + let _ = non_send_fut.await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR `std::cell::RefCell<i32>` cannot be shared between threads safely +} + +fn main() {} diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr new file mode 100644 index 00000000000..6ded3e475bc --- /dev/null +++ b/src/test/ui/async-await/issue-68112.stderr @@ -0,0 +1,56 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:34:5 + | +LL | fn require_send(_: impl Send) {} + | ---- required by this bound in `require_send` +... +LL | require_send(send_fut); + | ^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:31:17 + | +LL | let _ = non_send_fut.await; + | ^^^^^^^^^^^^ await occurs here on type `impl std::future::Future`, which is not `Send` + +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:43:5 + | +LL | fn require_send(_: impl Send) {} + | ---- required by this bound in `require_send` +... +LL | require_send(send_fut); + | ^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:40:17 + | +LL | let _ = make_non_send_future1().await; + | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl std::future::Future`, which is not `Send` + +error[E0277]: `std::cell::RefCell<i32>` cannot be shared between threads safely + --> $DIR/issue-68112.rs:60:5 + | +LL | fn require_send(_: impl Send) {} + | ---- required by this bound in `require_send` +... +LL | require_send(send_fut); + | ^^^^^^^^^^^^ `std::cell::RefCell<i32>` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::cell::RefCell<i32>>` + = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36 t:std::sync::Arc<std::cell::RefCell<i32>> {}]` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36 t:std::sync::Arc<std::cell::RefCell<i32>> {}]>` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `{std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}` + = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}]` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}]>` + = note: required because it appears within the type `impl std::future::Future` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index 73e2a92d815..49cd30e11a0 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -5,7 +5,7 @@ LL | fn assert_send<T: Send>(_: T) {} | ---- required by this bound in `assert_send` ... LL | assert_send(async { - | ^^^^^^^^^^^ future returned by `main` is not `Send` + | ^^^^^^^^^^^ future created by async block is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await @@ -14,7 +14,7 @@ note: future is not `Send` as this value is used across an await LL | bar(Foo(std::ptr::null())).await; | ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here | | | - | | has type `*const u8` + | | has type `*const u8` which is not `Send` | await occurs here, with `std::ptr::null()` maybe used later help: consider moving this into a `let` binding to create a shorter lived borrow --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 diff --git a/src/test/ui/generator/issue-68112.rs b/src/test/ui/generator/issue-68112.rs new file mode 100644 index 00000000000..9ab2abf7405 --- /dev/null +++ b/src/test/ui/generator/issue-68112.rs @@ -0,0 +1,56 @@ +#![feature(generators, generator_trait)] + +use std::{ + cell::RefCell, + sync::Arc, + pin::Pin, + ops::{Generator, GeneratorState}, +}; + +pub struct Ready<T>(Option<T>); +impl<T> Generator<()> for Ready<T> { + type Return = T; + type Yield = (); + fn resume(mut self: Pin<&mut Self>, _args: ()) -> GeneratorState<(), T> { + GeneratorState::Complete(self.0.take().unwrap()) + } +} +pub fn make_gen1<T>(t: T) -> Ready<T> { + Ready(Some(t)) +} + +fn require_send(_: impl Send) {} + +fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> { + make_gen1(Arc::new(RefCell::new(0))) +} + +fn test1() { + let send_gen = || { + let _non_send_gen = make_non_send_generator(); + yield; + }; + require_send(send_gen); + //~^ ERROR generator cannot be sent between threads +} + +pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> { + || { + yield; + t + } +} +fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> { + make_gen2(Arc::new(RefCell::new(0))) +} + +fn test2() { + let send_gen = || { + let _non_send_gen = make_non_send_generator2(); + yield; + }; + require_send(send_gen); + //~^ ERROR `std::cell::RefCell<i32>` cannot be shared between threads safely +} + +fn main() {} diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr new file mode 100644 index 00000000000..83536f2af14 --- /dev/null +++ b/src/test/ui/generator/issue-68112.stderr @@ -0,0 +1,40 @@ +error: generator cannot be sent between threads safely + --> $DIR/issue-68112.rs:33:5 + | +LL | fn require_send(_: impl Send) {} + | ---- required by this bound in `require_send` +... +LL | require_send(send_gen); + | ^^^^^^^^^^^^ generator is not `Send` + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>` +note: generator is not `Send` as this value is used across a yield + --> $DIR/issue-68112.rs:31:9 + | +LL | let _non_send_gen = make_non_send_generator(); + | ------------- has type `impl std::ops::Generator` which is not `Send` +LL | yield; + | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later +LL | }; + | - `_non_send_gen` is later dropped here + +error[E0277]: `std::cell::RefCell<i32>` cannot be shared between threads safely + --> $DIR/issue-68112.rs:52:5 + | +LL | fn require_send(_: impl Send) {} + | ---- required by this bound in `require_send` +... +LL | require_send(send_gen); + | ^^^^^^^^^^^^ `std::cell::RefCell<i32>` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::cell::RefCell<i32>>` + = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6 t:std::sync::Arc<std::cell::RefCell<i32>> {()}]` + = note: required because it appears within the type `impl std::ops::Generator` + = note: required because it appears within the type `impl std::ops::Generator` + = note: required because it appears within the type `{impl std::ops::Generator, ()}` + = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6 {impl std::ops::Generator, ()}]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/not-send-sync.rs b/src/test/ui/generator/not-send-sync.rs index 0db01c6f756..8ca5565fb2a 100644 --- a/src/test/ui/generator/not-send-sync.rs +++ b/src/test/ui/generator/not-send-sync.rs @@ -7,7 +7,7 @@ fn main() { fn assert_send<T: Send>(_: T) {} assert_sync(|| { - //~^ ERROR: future cannot be shared between threads safely + //~^ ERROR: generator cannot be shared between threads safely let a = Cell::new(2); yield; }); diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 5f5211b5092..5df2c1b52fb 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -11,21 +11,21 @@ LL | assert_send(|| { = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell<i32>` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell<i32> _]` -error: future cannot be shared between threads safely +error: generator cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 | LL | fn assert_sync<T: Sync>(_: T) {} | ---- required by this bound in `main::assert_sync` ... LL | assert_sync(|| { - | ^^^^^^^^^^^ future returned by `main` is not `Sync` + | ^^^^^^^^^^^ generator is not `Sync` | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>` -note: future is not `Sync` as this value is used across an yield +note: generator is not `Sync` as this value is used across a yield --> $DIR/not-send-sync.rs:12:9 | LL | let a = Cell::new(2); - | - has type `std::cell::Cell<i32>` + | - has type `std::cell::Cell<i32>` which is not `Sync` LL | yield; | ^^^^^ yield occurs here, with `a` maybe used later LL | }); |
