1
Fork 0

Rollup merge of #80614 - 1000teslas:issue-78938-fix, r=tmandry

Explain why borrows can't be held across yield point in async blocks

For https://github.com/rust-lang/rust/issues/78938.
This commit is contained in:
Mara Bos 2021-01-16 17:29:49 +00:00 committed by GitHub
commit af5b0d9883
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 5 deletions

View file

@ -50,3 +50,24 @@ fn foo() -> Box<Fn(u32) -> u32> {
Now that the closure has its own copy of the data, there's no need to worry Now that the closure has its own copy of the data, there's no need to worry
about safety. about safety.
This error may also be encountered while using `async` blocks:
```compile_fail,E0373,edition2018
use std::future::Future;
async fn f() {
let v = vec![1, 2, 3i32];
spawn(async { //~ ERROR E0373
println!("{:?}", v)
});
}
fn spawn<F: Future + Send + 'static>(future: F) {
unimplemented!()
}
```
Similarly to closures, `async` blocks are not executed immediately and may
capture closed-over data by reference. For more information, see
https://rust-lang.github.io/async-book/03_async_await/01_chapter.html.

View file

@ -1318,21 +1318,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
let msg = match category { match category {
ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
format!("{} is returned here", kind) let msg = format!("{} is returned here", kind);
err.span_note(constraint_span, &msg);
} }
ConstraintCategory::CallArgument => { ConstraintCategory::CallArgument => {
fr_name.highlight_region_name(&mut err); fr_name.highlight_region_name(&mut err);
format!("function requires argument type to outlive `{}`", fr_name) if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
err.note(
"async blocks are not executed immediately and must either take a \
reference or ownership of outside variables they use",
);
} else {
let msg = format!("function requires argument type to outlive `{}`", fr_name);
err.span_note(constraint_span, &msg);
}
} }
_ => bug!( _ => bug!(
"report_escaping_closure_capture called with unexpected constraint \ "report_escaping_closure_capture called with unexpected constraint \
category: `{:?}`", category: `{:?}`",
category category
), ),
}; }
err.span_note(constraint_span, &msg);
err err
} }

View file

@ -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() {}

View file

@ -0,0 +1,21 @@
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: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use
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`.