Manually drop MutexGuard still raise `Future is not Send' error

I have this code: Rust Playground

async fn foo() {
    
}

fn test() -> impl std::future::Future<Output = ()> + Send {
    let a = 1u32;
    let mtx = std::sync::Mutex::new(a);
    
    async move {
        let g = mtx.lock().unwrap();
        if a > 0 {
            drop(g); // manually drop MutexGuard here
            foo().await;    
        }
    }
}

fn main() {
    test();
    println!("Hello, world!");
}

I know MutexGuard can not cross await, but when drop it manually, compiler still raise error

Compiling playground v0.0.1 (/playground)
error: future cannot be sent between threads safely
  --> src/main.rs:5:14
   |
5  | fn test() -> impl std::future::Future<Output = ()> + Send {
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
   |
   = help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`
note: future is not `Send` as this value is used across an await
  --> src/main.rs:13:13
   |
10 |         let g = mtx.lock().unwrap();
   |             - has type `MutexGuard<'_, u32>` which is not `Send`
...
13 |             foo().await;    
   |             ^^^^^^^^^^^ await occurs here, with `g` maybe used later
14 |         }
15 |     }
   |     - `g` is later dropped here

it says g is later dropped at end of block, but in fact it has been dropped before await point.
Is this a compiler problem?

1 Like

The compiler is just too stupid to accept it.

There has to be an actual scope before it will accept it.

1 Like

Is there an improvement plan for this issue?

This is the canonical issue:

And here is the issue tackling it (and other instances of "the compiler being stupid in that regard" being problematic):

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.