Skip to content

Misleading help suggests Sync bound when shareable reference is passed across or into await #129105

Open
@mzabaluev

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)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.D-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions