Skip to content

Async function using non-across-yield non-Send value is Send only if the usage is inside curly brackets #61950

@tirr-c

Description

@tirr-c

The title might be confusing, but here is my test code:

#![feature(async_await)]
use std::sync::{Arc, Mutex};

async fn div2(x: usize) -> usize {
    x / 2
}

async fn foo_pass(m: Arc<Mutex<usize>>) -> usize {
    let y = {
        let x = m.lock().unwrap(); // x: !Send
        *x + 1
    }; // x is dropped here
    div2(y).await
}

async fn foo_fail(m: Arc<Mutex<usize>>) -> usize {
    let x = m.lock().unwrap(); // x: !Send
    let y = *x + 1;
    drop(x); // x is dropped here (maybe)
    div2(y).await
}

struct CheckSend<T: Send>(T);

pub fn pass() {
    let m = Arc::new(Mutex::new(5));
    let _ = CheckSend(foo_pass(m.clone()));
}

pub fn fail() {
    let m = Arc::new(Mutex::new(5));
    let _ = CheckSend(foo_fail(m.clone()));
}

Playground

error[E0277]: `std::sync::MutexGuard<'_, usize>` cannot be sent between threads safely
  --> src/lib.rs:32:13
   |
32 |     let _ = CheckSend(foo_fail(m.clone()));
   |             ^^^^^^^^^ `std::sync::MutexGuard<'_, usize>` cannot be sent between threads safely
   |
   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, usize>`
   = note: required because it appears within the type `for<'r> {std::sync::Arc<std::sync::Mutex<usize>>, std::sync::MutexGuard<'r, usize>, usize, impl std::future::Future, ()}`
   = note: required because it appears within the type `[static generator@src/lib.rs:16:50: 21:2 m:std::sync::Arc<std::sync::Mutex<usize>> for<'r> {std::sync::Arc<std::sync::Mutex<usize>>, std::sync::MutexGuard<'r, usize>, usize, impl std::future::Future, ()}]`
   = note: required because it appears within the type `std::future::GenFuture<[static generator@src/lib.rs:16:50: 21:2 m:std::sync::Arc<std::sync::Mutex<usize>> for<'r> {std::sync::Arc<std::sync::Mutex<usize>>, std::sync::MutexGuard<'r, usize>, usize, impl std::future::Future, ()}]>`
   = note: required because it appears within the type `impl std::future::Future`
   = note: required because it appears within the type `impl std::future::Future`
note: required by `CheckSend`
  --> src/lib.rs:23:1
   |
23 | struct CheckSend<T: Send>(T);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: `std::sync::MutexGuard<'_, usize>` cannot be sent between threads safely
  --> src/lib.rs:32:13
   |
32 |     let _ = CheckSend(foo_fail(m.clone()));
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::sync::MutexGuard<'_, usize>` cannot be sent between threads safely
   |
   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, usize>`
   = note: required because it appears within the type `for<'r> {std::sync::Arc<std::sync::Mutex<usize>>, std::sync::MutexGuard<'r, usize>, usize, impl std::future::Future, ()}`
   = note: required because it appears within the type `[static generator@src/lib.rs:16:50: 21:2 m:std::sync::Arc<std::sync::Mutex<usize>> for<'r> {std::sync::Arc<std::sync::Mutex<usize>>, std::sync::MutexGuard<'r, usize>, usize, impl std::future::Future, ()}]`
   = note: required because it appears within the type `std::future::GenFuture<[static generator@src/lib.rs:16:50: 21:2 m:std::sync::Arc<std::sync::Mutex<usize>> for<'r> {std::sync::Arc<std::sync::Mutex<usize>>, std::sync::MutexGuard<'r, usize>, usize, impl std::future::Future, ()}]>`
   = note: required because it appears within the type `impl std::future::Future`
   = note: required because it appears within the type `impl std::future::Future`
note: required by `CheckSend`
  --> src/lib.rs:23:1
   |
23 | struct CheckSend<T: Send>(T);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions