Description
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