Repository: rust
Issue: rustc fails to prove `Send`ness for an `async` block where a `!Send` value is dropped before an `.await` point
Labels: C-bug,A-async-await,AsyncAwait-Triaged,F-coroutines

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

I tried this code: ([playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=3097a0388ca33bda2efa385a2c5394e5))

```rust
#[tokio::main]
async fn main() {
    let (tx, rx) = tokio::sync::watch::channel(vec![1, 1, 4, 5, 1, 4]);
    let mut binding = rx.clone();
    tokio::spawn(async move {
        let value = binding.borrow();
        let len = value.len();
        drop(value);
        println!("len: {}", len);
        binding.changed().await
            .expect("watch error");
    }).await;
    println!("{:?}", rx.borrow());
}
```

I expected to see this happen: the code passes compilation.

Instead, this happened:

```
error: future cannot be sent between threads safely
   --> src/main.rs:5:5
    |
5   | /     tokio::spawn(async move {
6   | |         let value = binding.borrow();
7   | |         let len = value.len();
8   | |         drop(value);
...   |
11  | |             .expect("watch error");
12  | |     }).await;
    | |______^ future created by async block is not `Send`
    |
    = help: within `{async block@src/main.rs:5:18: 5:28}`, the trait `Send` is not implemented for `std::sync::RwLockReadGuard<'_, Vec<i32>>`, which is required by `{async block@src/main.rs:5:18: 5:28}: Send`
note: future is not `Send` as this value is used across an await
   --> src/main.rs:10:27
    |
6   |         let value = binding.borrow();
    |             ----- has type `tokio::sync::watch::Ref<'_, Vec<i32>>` which is not `Send`
...
10  |         binding.changed().await
    |                           ^^^^^ await occurs here, with `value` maybe used later
note: required by a bound in `tokio::spawn`
   --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.38.0/src/task/spawn.rs:166:21
    |
164 |     pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
    |            ----- required by a bound in this function
165 |     where
166 |         F: Future + Send + 'static,
    |                     ^^^^ required by this bound in `spawn`

error: future cannot be sent between threads safely
   --> src/main.rs:5:5
    |
5   | /     tokio::spawn(async move {
6   | |         let value = binding.borrow();
7   | |         let len = value.len();
8   | |         drop(value);
...   |
11  | |             .expect("watch error");
12  | |     }).await;
    | |______^ future created by async block is not `Send`
    |
    = help: within `{async block@src/main.rs:5:18: 5:28}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{async block@src/main.rs:5:18: 5:28}: Send`
note: future is not `Send` as this value is used across an await
   --> src/main.rs:10:27
    |
6   |         let value = binding.borrow();
    |             ----- has type `tokio::sync::watch::Ref<'_, Vec<i32>>` which is not `Send`
...
10  |         binding.changed().await
    |                           ^^^^^ await occurs here, with `value` maybe used later
note: required by a bound in `tokio::spawn`
   --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.38.0/src/task/spawn.rs:166:21
    |
164 |     pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
    |            ----- required by a bound in this function
165 |     where
166 |         F: Future + Send + 'static,
    |                     ^^^^ required by this bound in `spawn`
```

However, this code works fine: ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=221df033c3287aee245fad8b9e4cabe1))

```rust
#[tokio::main]
async fn main() {
    let (tx, rx) = tokio::sync::watch::channel(vec![1, 1, 4, 5, 1, 4]);
    let mut binding = rx.clone();
    tokio::spawn(async move {
        let len = {
            let value = binding.borrow();
            value.len()
        };
        println!("len: {}", len);
        binding.changed().await
            .expect("watch error");
    }).await;
    println!("{:?}", rx.borrow());
}
```

Meta: nightly rust (1.81.0-nightly 2024-07-12) and stable rust (1.79.0) behave similarly. 

I have constructed a minimum reproducible version:
```rust
#![allow(unused)]

struct NotSend(std::marker::PhantomData<*mut ()>);

impl NotSend {
    fn new() -> Self {
        Self(std::marker::PhantomData)
    }
}

unsafe impl Sync for NotSend {}

#[derive(Clone)]
struct WatchRecv;

impl WatchRecv {
    fn borrow(&self) -> Ref<'_> {
        Ref(self, NotSend::new())
    }
}

struct Ref<'a>(&'a WatchRecv, NotSend);

fn assert_send<F: std::future::Future + Send>(f: F) -> F { f }

impl Ref<'_> {
    fn len(&self) -> usize { 0 }
}

async fn another_future() {
    loop {}
}

async fn real_main() {
    let rx = WatchRecv;
    let mut binding = rx.clone();
    assert_send(async move {
        // /*
        // This doesn't works.
        let value = binding.borrow();
        let len = value.len();
        drop(value);
        println!("len: {len}");
        // */
        /*
        // This works.
        let len = {
            let value = binding.borrow();
            value.len()
        };
        */
        another_future().await;
    }).await;
    println!("{:?}", rx.borrow().len());
}
```