Skip to content

Destructor of one struct field depends on other without any correlation #78940

Open
@MihirLuthra

Description

@MihirLuthra

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

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:

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.

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
Backtrace

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)

cc @jyn514

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-DSTsArea: Dynamically-sized types (DSTs)A-lifetimesArea: Lifetimes / regionsA-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions