Closed
Description
Consider the following code:
use std::sync::Arc;
use tokio::runtime::Runtime; // 0.3.1
async fn f() {
let room_ref = Arc::new(Vec::new());
let gameloop_handle = Runtime::new().unwrap().spawn(async {
game_loop(Arc::clone(&room_ref))
});
gameloop_handle.await;
}
fn game_loop(v: Arc<Vec<usize>>) {}
The error message has a helpful hint:
help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword
|
7 | let gameloop_handle = Runtime::new().unwrap().spawn(async move {
8 | game_loop(Arc::clone(&room_ref))
9 | });
But it doesn't explain very well why move
is necessary:
error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
--> src/lib.rs:7:63
|
7 | let gameloop_handle = Runtime::new().unwrap().spawn(async {
| _______________________________________________________________^
8 | | game_loop(Arc::clone(&room_ref))
| | -------- `room_ref` is borrowed here
9 | | });
| |_____^ may outlive borrowed value `room_ref`
|
note: function requires argument type to outlive `'static`
--> src/lib.rs:7:57
|
7 | let gameloop_handle = Runtime::new().unwrap().spawn(async {
| _________________________________________________________^
8 | | game_loop(Arc::clone(&room_ref))
9 | | });
| |_____^
In particular, 'async block may outlive the current function' makes no sense without a very good mental model of async: the future is await
ed within the current function, so of course it can't outlive it. The thing to realize here is that even though it's written as one function, it's actually two: one executed before the yield point, and one after, and the stack space for the first function goes away when you call await
.
It would be nice to instead say something like
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
Metadata
Metadata
Assignees
Labels
Area: Async & AwaitArea: Messages for errors, warnings, and lintsArea: Lifetimes / regionsAsync-await issues that have been triaged during a working group meeting.Diagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint; hard to understand for new users.Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.Relevant to the compiler team, which will review and decide on the PR/issue.