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..0d269b1801b --- /dev/null +++ b/src/test/ui/async-await/issue-68112.rs @@ -0,0 +1,53 @@ +// edition:2018 + +use std::{ + future::Future, + cell::RefCell, + sync::Arc, + pin::Pin, + task::{Context, Poll}, +}; + +fn require_send(_: impl Send) {} + +struct Ready(Option); +impl Future for Ready { + type Output = T; + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0.take().unwrap()) + } +} +fn ready(t: T) -> Ready { + Ready(Some(t)) +} + +fn make_non_send_future1() -> impl Future>> { + 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 +} + +async fn ready2(t: T) -> T { t } +fn make_non_send_future2() -> impl Future>> { + ready2(Arc::new(RefCell::new(0))) +} + +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` 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..461967b7d8b --- /dev/null +++ b/src/test/ui/async-await/issue-68112.stderr @@ -0,0 +1,45 @@ +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 returned by `test1` is not `Send` + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-68112.rs:32:9 + | +LL | let non_send_fut = make_non_send_future1(); + | ------------ has type `impl std::future::Future` +LL | let _ = non_send_fut.await; +LL | ready(0).await; + | ^^^^^^^^ await occurs here, with `non_send_fut` maybe used later +LL | }; + | - `non_send_fut` is later dropped here + +error[E0277]: `std::cell::RefCell` cannot be shared between threads safely + --> $DIR/issue-68112.rs:49:5 + | +LL | fn require_send(_: impl Send) {} + | ------------ ---- required by this bound in `require_send` +... +LL | require_send(send_fut); + | ^^^^^^^^^^^^ `std::cell::RefCell` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc>` + = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:38:31: 38:36 t:std::sync::Arc> {}]` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:38:31: 38:36 t:std::sync::Arc> {}]>` + = 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}` + = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:44:26: 48:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready}]` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:44:26: 48:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready}]>` + = note: required because it appears within the type `impl std::future::Future` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/issue-68112.rs b/src/test/ui/generator/issue-68112.rs new file mode 100644 index 00000000000..ee62cbff08f --- /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(Option); +impl Generator<()> for Ready { + 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) -> Ready { + Ready(Some(t)) +} + +fn require_send(_: impl Send) {} + +fn make_non_send_generator() -> impl Generator>> { + 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 future cannot be sent between threads +} + +pub fn make_gen2(t: T) -> impl Generator { + || { + yield; + t + } +} +fn make_non_send_generator2() -> impl Generator>> { + 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` 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..b98afd47b56 --- /dev/null +++ b/src/test/ui/generator/issue-68112.stderr @@ -0,0 +1,40 @@ +error: future 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); + | ^^^^^^^^^^^^ future returned by `test1` is not `Send` + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` +note: future is not `Send` as this value is used across an yield + --> $DIR/issue-68112.rs:31:9 + | +LL | let _non_send_gen = make_non_send_generator(); + | ------------- has type `impl std::ops::Generator` +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` 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` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc>` + = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6 t:std::sync::Arc> {()}]` + = 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`.