diff options
| author | 1000teslas <47207223+1000teslas@users.noreply.github.com> | 2021-01-02 22:03:21 +1100 |
|---|---|---|
| committer | 1000teslas <47207223+1000teslas@users.noreply.github.com> | 2021-01-10 16:47:40 +1100 |
| commit | 5ccef564560df65db0cb761cb27751f15821f1af (patch) | |
| tree | 39c668fd481b24801f1c91d5b23e227aa482fa67 | |
| parent | ef589490a709984d3be80c9b59a1a10a4dd05e3c (diff) | |
| download | rust-5ccef564560df65db0cb761cb27751f15821f1af.tar.gz rust-5ccef564560df65db0cb761cb27751f15821f1af.zip | |
Explain why borrows can't be held across yield point in async blocks
3 files changed, 73 insertions, 0 deletions
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 0bb09e26f03..1dd102f4f34 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1323,6 +1323,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { suggestion, Applicability::MachineApplicable, ); + if let Some(generator_kind) = use_span.generator_kind() { + if let GeneratorKind::Async(_) = generator_kind { + err.note( + "borrows cannot be held across a yield point, because the stack space of the current \ + function is not preserved", + ); + err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \ + for more information"); + } + } let msg = match category { ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.rs b/src/test/ui/async-await/issues/issue-78938-async-block.rs new file mode 100644 index 00000000000..e3d8eb73772 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-78938-async-block.rs @@ -0,0 +1,33 @@ +// edition:2018 + +use std::{sync::Arc, future::Future, pin::Pin, task::{Context,Poll}}; + +async fn f() { + let room_ref = Arc::new(Vec::new()); + + let gameloop_handle = spawn(async { //~ ERROR E0373 + game_loop(Arc::clone(&room_ref)) + }); + gameloop_handle.await; +} + +fn game_loop(v: Arc<Vec<usize>>) {} + +fn spawn<F>(future: F) -> JoinHandle +where + F: Future + Send + 'static, + F::Output: Send + 'static, +{ + loop {} +} + +struct JoinHandle; + +impl Future for JoinHandle { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + loop {} + } +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr new file mode 100644 index 00000000000..83cf1a5bc46 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr @@ -0,0 +1,30 @@ +error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function + --> $DIR/issue-78938-async-block.rs:8:39 + | +LL | let gameloop_handle = spawn(async { + | _______________________________________^ +LL | | game_loop(Arc::clone(&room_ref)) + | | -------- `room_ref` is borrowed here +LL | | }); + | |_____^ may outlive borrowed value `room_ref` + | + = note: borrows cannot be held across a yield point, because the stack space of the current function is not preserved + = help: see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor for more information +note: function requires argument type to outlive `'static` + --> $DIR/issue-78938-async-block.rs:8:33 + | +LL | let gameloop_handle = spawn(async { + | _________________________________^ +LL | | game_loop(Arc::clone(&room_ref)) +LL | | }); + | |_____^ +help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword + | +LL | let gameloop_handle = spawn(async move { +LL | game_loop(Arc::clone(&room_ref)) +LL | }); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. |
