- Notifications
You must be signed in to change notification settings - Fork 13.9k
Open
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.D-confusingDiagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
#59245 results in an error that may be difficult to interpret when structuring generic async code:
use std::fmt::Display; async fn run(mut state: impl Display) { do_stuff(&state).await; // ... } async fn do_stuff(state: &impl Display) { println!("{state}"); } fn spawn_task<T>(state: T) where T: Display + Send + 'static, { tokio::spawn(run(state)); }
The compiler (as of 1.82.0-nightly (80eb5a8 2024-08-13)) produces this error output:
error[E0277]: `T` cannot be shared between threads safely --> src/main.rs:16:18 | 16 | tokio::spawn(run(state)); | ------------ ^^^^^^^^^^ `T` cannot be shared between threads safely | | | required by a bound introduced by this call | = note: required for `&T` to implement `Send` note: required because it's used within this `async` fn body --> src/main.rs:8:41 | 8 | async fn do_stuff(state: &impl Display) { | _________________________________________^ 9 | | println!("{state}"); 10 | | } | |_^ note: required because it's used within this `async` fn body --> src/main.rs:3:35 | 3 | async fn run(state: impl Display) { | ___________________________________^ 4 | | do_stuff(&state).await; 5 | | // ... 6 | | } | |_^ note: required by a bound in `tokio::spawn` --> /home/mzabaluev/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.39.2/src/task/spawn.rs:167:21 | 165 | pub fn spawn<F>(future: F) -> JoinHandle<F::Output> | ----- required by a bound in this function 166 | where 167 | F: Future + Send + 'static, | ^^^^ required by this bound in `spawn` help: consider further restricting this bound | 14 | T: Display + Send + 'static + std::marker::Sync, | +++++++++++++++++++
A non-restrictive, but also unintuitive, solution is to make the reference passed to do_stuff
mutable (i.e. provably exclusive), even though mutability is not required by the function body.
Desired outcome
The help heuristic should detect that the Sync
bound arises due to a shareable reference becoming a member of an async closure for which Send
is required, and suggest using an exclusive reference as an alternative to restricting the bound.
Originally posted by @mzabaluev in #59245 (comment)
Metadata
Metadata
Assignees
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.D-confusingDiagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.