Repository: rust
Issue: Unexpected partial move in closure for `Copy` field
Labels: C-bug,A-edition-2021

<!--
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.
-->

Hi! Recently we have encountered an issue for metrics reporting. We are using [futures_async_stream::try_stream](https://docs.rs/futures-async-stream/latest/futures_async_stream/#try_stream) to convert our iterators into stream, and we implement a struct `Stats` to collect useful metrics and report the metrics when `Stats` gets dropped. 

The `try_stream` macro generates the internal code of the stream by using rust `Generator`, and the `Stats` is mutably moved in the generator closure, and will get modified while collecting the metrics. Under our expectation, we are able to collect some correct metrics before the `Stats` gets dropped. However, in our observation, the `Stats` is not modified at all, and none of the metrics is collected.

After some experiment, we figure out that there is a confusing behavior in the rust code. We have minimized our code, and the following code is a minimum reproducible code for the unexpected behavior.

I tried this code:

```rust
#![feature(generators, generator_trait)]

use std::ops::Generator;
use std::pin::Pin;

#[derive(Default, Debug)]
struct SomethingElse {
    num: usize,
}

#[derive(Default, Debug)]
struct TestStats {
    total_items: usize,
    some: SomethingElse,
}

impl Drop for TestStats {
    fn drop(&mut self) {
        println!("dropped: {} {:?}", self.total_items, self.some);
    }
}

pub fn main() {
    let mut stats = TestStats::default();
    
    let mut generator = Box::pin(move || {
        // println!("{:?}", stats);
        stats.total_items += 1;
        yield 2;
    });
    
    
    Pin::new(&mut generator).resume(());
    
}
```

We expected to see this output: 
```
dropped: 1 SomethingElse { num: 0 }
```
which means that `stats.total_items += 1` gets executed once.


Instead, we saw
```
dropped: 0 SomethingElse { num: 0 }
```
which means that `stats.total_items += 1` did not get executed on `stats.total_items`.

After we uncomment the line `println!("{:?}", stats);` and reference the whole `stats`,
```rust
#![feature(generators, generator_trait)]

use std::ops::Generator;
use std::pin::Pin;

#[derive(Default, Debug)]
struct SomethingElse {
    num: usize,
}

#[derive(Default, Debug)]
struct TestStats {
    total_items: usize,
    some: SomethingElse,
}

impl Drop for TestStats {
    fn drop(&mut self) {
        println!("dropped: {} {:?}", self.total_items, self.some);
    }
}

pub fn main() {
    let mut stats = TestStats::default();
    
    let mut generator = Box::pin(move || {
        println!("{:?}", stats); // Previously commented !!!
        stats.total_items += 1;
        yield 2;
    });
    
    
    Pin::new(&mut generator).resume(());
    
}
```
, the output gets as expected.

```
TestStats { total_items: 0, some: SomethingElse { num: 0 } }
dropped: 1 SomethingElse { num: 0 }
```

### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

The code can be run on [Rust Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021). 

```
<version>
1.70.0-nightly 2023-03-05 7820b62
```

<!--
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
-->
<details><summary>Backtrace</summary>
<p>

```
<backtrace>
```

</p>
</details>