Repository: rust
Issue: Destructor of one struct field depends on other without any correlation
Labels: A-lifetimes,A-trait-system,A-DSTs,T-compiler,C-bug

I have a struct with 2 fields. Destructor of one field depends on the other without any correlation (at least I don't see any). Below is a short snippet showing the bugged behaviour. Main code can be found on this stackoverflow post: [StackOverflow question](https://stackoverflow.com/questions/64769867/destructor-of-one-struct-field-depends-on-other-without-any-correlation)

```rust
struct Iter<'a> {
    inner: Option<Box<dyn Iterator<Item = &'a str>>>,
}

struct BuilderData<'a> {
    builder_struct_name: &'a str,
    fields_mapped_iter: Iter<'a>,
}

fn derive() {
    let fields_mapped_iter = Iter { inner: None };
    let builder_struct_name = &String::new();
    let _ = BuilderData {
        builder_struct_name,
        fields_mapped_iter,
    };
}

fn main() {}
```

This produces the following error:
```
error[E0716]: temporary value dropped while borrowed
  --> /Users/mihir/fquicktest/data/user_data/instances/jyn_code.rs:12:32
   |
12 |     let builder_struct_name = &String::new();
   |                                ^^^^^^^^^^^^^ creates a temporary which is freed while still in use
...
17 | }
   | -
   | |
   | temporary value is freed at the end of this statement
   | borrow might be used here, when `fields_mapped_iter` is dropped and runs the destructor for type `Iter<'_>`
   |
   = note: consider using a `let` binding to create a longer lived value

error: aborting due to previous error
```

The error is telling that `fields_mapped_iter`'s destructor depends on `builder_struct_name` for some reason.

If I swap the declaration lines to make it like this:

```rust
let builder_struct_name = &String::new();
let fields_mapped_iter = Iter { inner: None };
```
Because `fields_mapped_iter` is moved below `builder_struct_name`, `fields_mapped_iter`'s destructor is called first and so that time `builder_struct_name` is alive and no error is shown by the compiler.

Although, don't really understand why does the destructor even depend on another field.

Moreover, if the struct is changed to use a separate lifetime `'b` for `fields_mapped_iter` as shown below, all the issues go away and this destructor dependency is gone.

```rust
struct BuilderData<'a, 'b> {
    builder_struct_name: &'a str,
    fields_mapped_iter: Iter<'b>,
}
```

### Meta
Tested on both stable and nightly and the results are same.

**Stable Version**
```
mihir@Mihirs-MacBook-Pro rust_issue % rustc --version --verbose             
rustc 1.42.0 (b8cedc004 2020-03-09)
binary: rustc
commit-hash: b8cedc00407a4c56a3bda1ed605c6fc166655447
commit-date: 2020-03-09
host: x86_64-apple-darwin
release: 1.42.0
LLVM version: 9.0

```

**Nightly Version**
```
mihir@Mihirs-MacBook-Pro rust_issue % rustc --version --verbose             
rustc 1.49.0-nightly (1eaadebb3 2020-10-21)
binary: rustc
commit-hash: 1eaadebb3dee31669c7649b32747381d11614fae
commit-date: 2020-10-21
host: x86_64-apple-darwin
release: 1.49.0-nightly
LLVM version: 11.0
```

<details><summary>Backtrace</summary>
<p>

```
mihir@Mihirs-MacBook-Pro rust_issue % RUST_BACKTRACE=1 cargo build --verbose
   Compiling rust_issue v0.1.0 (/Users/mihir/rust_issue/rust_issue)
     Running `rustc --crate-name rust_issue --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=02e048f8a4b6614d -C extra-filename=-02e048f8a4b6614d --out-dir /Users/mihir/rust_issue/rust_issue/target/debug/deps -C incremental=/Users/mihir/rust_issue/rust_issue/target/debug/incremental -L dependency=/Users/mihir/rust_issue/rust_issue/target/debug/deps`
error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:12:32
   |
12 |     let builder_struct_name = &String::new();
   |                                ^^^^^^^^^^^^^ creates a temporary which is freed while still in use
...
17 | }
   | -
   | |
   | temporary value is freed at the end of this statement
   | borrow might be used here, when `fields_mapped_iter` is dropped and runs the destructor for type `Iter<'_>`
   |
   = note: consider using a `let` binding to create a longer lived value

error: aborting due to previous error

For more information about this error, try `rustc --explain E0716`.
error: could not compile `rust_issue`.

Caused by:
  process didn't exit successfully: `rustc --crate-name rust_issue --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=02e048f8a4b6614d -C extra-filename=-02e048f8a4b6614d --out-dir /Users/mihir/rust_issue/rust_issue/target/debug/deps -C incremental=/Users/mihir/rust_issue/rust_issue/target/debug/incremental -L dependency=/Users/mihir/rust_issue/rust_issue/target/debug/deps` (exit code: 1)
```

</p>
</details>

cc @jyn514