Skip to content

Commit 5ccef56

Browse files
Explain why borrows can't be held across yield point in async blocks
1 parent ef58949 commit 5ccef56

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13231323
suggestion,
13241324
Applicability::MachineApplicable,
13251325
);
1326+
if let Some(generator_kind) = use_span.generator_kind() {
1327+
if let GeneratorKind::Async(_) = generator_kind {
1328+
err.note(
1329+
"borrows cannot be held across a yield point, because the stack space of the current \
1330+
function is not preserved",
1331+
);
1332+
err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \
1333+
for more information");
1334+
}
1335+
}
13261336

13271337
let msg = match category {
13281338
ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// edition:2018
2+
3+
use std::{sync::Arc, future::Future, pin::Pin, task::{Context,Poll}};
4+
5+
async fn f() {
6+
let room_ref = Arc::new(Vec::new());
7+
8+
let gameloop_handle = spawn(async { //~ ERROR E0373
9+
game_loop(Arc::clone(&room_ref))
10+
});
11+
gameloop_handle.await;
12+
}
13+
14+
fn game_loop(v: Arc<Vec<usize>>) {}
15+
16+
fn spawn<F>(future: F) -> JoinHandle
17+
where
18+
F: Future + Send + 'static,
19+
F::Output: Send + 'static,
20+
{
21+
loop {}
22+
}
23+
24+
struct JoinHandle;
25+
26+
impl Future for JoinHandle {
27+
type Output = ();
28+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
29+
loop {}
30+
}
31+
}
32+
33+
fn main() {}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
2+
--> $DIR/issue-78938-async-block.rs:8:39
3+
|
4+
LL | let gameloop_handle = spawn(async {
5+
| _______________________________________^
6+
LL | | game_loop(Arc::clone(&room_ref))
7+
| | -------- `room_ref` is borrowed here
8+
LL | | });
9+
| |_____^ may outlive borrowed value `room_ref`
10+
|
11+
= note: borrows cannot be held across a yield point, because the stack space of the current function is not preserved
12+
= help: see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor for more information
13+
note: function requires argument type to outlive `'static`
14+
--> $DIR/issue-78938-async-block.rs:8:33
15+
|
16+
LL | let gameloop_handle = spawn(async {
17+
| _________________________________^
18+
LL | | game_loop(Arc::clone(&room_ref))
19+
LL | | });
20+
| |_____^
21+
help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword
22+
|
23+
LL | let gameloop_handle = spawn(async move {
24+
LL | game_loop(Arc::clone(&room_ref))
25+
LL | });
26+
|
27+
28+
error: aborting due to previous error
29+
30+
For more information about this error, try `rustc --explain E0373`.

0 commit comments

Comments
 (0)