Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potentially misleading error when holding a reference into a guard across await point #136349

Closed
CeNiEi opened this issue Jan 31, 2025 · 2 comments
Labels
A-async-await Area: Async & Await C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@CeNiEi
Copy link

CeNiEi commented Jan 31, 2025

I tried this code:

use parking_lot;
use tokio; // 1.43.0 // 0.12.3

use std::collections::HashMap;

struct Temp {
    temp: parking_lot::RwLock<HashMap<i32, Vec<i32>>>,
    timer: tokio::time::Interval,
}

impl Temp {
    fn poll(mut self) {
        tokio::task::spawn(async move {
            let mut _guard = self.temp.write();
            let _ = _guard.get_mut(&0);

            std::mem::drop(_guard);
            self.timer.tick().await;
        });
    }
}

fn main() {}

Since we are already dropping the _guard, before calling await. This future should be Send and should compile successfully.

But for some reason the compiler complains that

   Compiling playground v0.0.1 (/playground)
error: future cannot be sent between threads safely
   --> src/main.rs:13:9
    |
13  | /         tokio::task::spawn(async move {
14  | |             let mut _guard = self.temp.write();
15  | |             let _ = _guard.get_mut(&0);
...   |
18  | |             self.timer.tick().await;
19  | |         });
    | |__________^ future created by async block is not `Send`
    |
    = help: within `{async block@src/main.rs:13:28: 13:38}`, the trait `Send` is not implemented for `*mut ()`
note: future is not `Send` as this value is used across an await
   --> src/main.rs:18:31
    |
14  |             let mut _guard = self.temp.write();
    |                 ---------- has type `parking_lot::lock_api::RwLockWriteGuard<'_, parking_lot::RawRwLock, HashMap<i32, Vec<i32>>>` which is not `Send`
...
18  |             self.timer.tick().await;
    |                               ^^^^^ await occurs here, with `mut _guard` maybe used later
note: required by a bound in `tokio::spawn`
   --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.43.0/src/task/spawn.rs:168:21
    |
166 |     pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
    |            ----- required by a bound in this function
167 |     where
168 |         F: Future + Send + 'static,
    |                     ^^^^ required by this bound in `spawn`

The issue is probably caused the let _ = _guard.get_mut(&0); statement.
I guess a more reasonable error could be that bound variable is holding a ref into the guard, which can be used later (I am not sure if that is infact the case).

Meta

Happens on Stable 1.84.1 and Nightly 1.86.0 as well
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e5a6b1f10131890af79c6c6ab4e991e1

@CeNiEi CeNiEi added the C-bug Category: This is a bug. label Jan 31, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jan 31, 2025
@theemathas
Copy link
Contributor

Duplicate of #63768

Can be worked around by adding a block around the scope of the guard.

        tokio::task::spawn(async move {
            {
                let mut _guard = self.temp.write();
                let _ = _guard.get_mut(&0);
            }
            self.timer.tick().await;
        });

@CeNiEi
Copy link
Author

CeNiEi commented Jan 31, 2025

Thanks a lot.
Closing this 👍

@CeNiEi CeNiEi closed this as completed Jan 31, 2025
@saethlin saethlin added T-lang Relevant to the language team, which will review and decide on the PR/issue. C-feature-request Category: A feature request, i.e: not implemented / a PR. A-async-await Area: Async & Await and removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Feb 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants