Up until now, I assumed that a temporary was destructed at the end of the evaluation of the statement that had spawned it.
However, it appears that there is an exception made when using a temporary to initialize the field of a struct
.
PeterHall helpfully provided a simple code sample illustrating the difference in a comment to his answer, which I've simplified complicated a bit:
struct Wrapper<'a> {
cmd: &'a Cmd<'a>,
}
struct Cmd<'a> {
args: &'a Option<String>,
}
impl <'a> Cmd<'a> {
fn new(args: &'a Option<String>) -> Cmd<'a> {
Cmd {
args: args,
}
}
}
pub fn main() {
// OK
let cmd = Cmd {
args: &None,
};
// OK
let cmd = Wrapper {
cmd: &Cmd {
args: &None,
}
};
// Lifetime error
let cmd = Some(Cmd {
args: &None,
});
// Lifetime error
let cmd = Cmd::new(&None);
}
So, what is the exact rule for when a temporary is destructed?
Let's look at the second failing line first:
let cmd = Cmd::new(&None);
&None
creates a temporary with a lifetime of the single line. Cmd::new
returns a Cmd
that has the same lifetime. Then we have attempt to store that temporary in a variable with let
.
The Rust reference states:
When a temporary rvalue is being created that is assigned into a let declaration, however, the temporary is created with the lifetime of the enclosing block instead...
It tries to increase the lifetime of the Cmd
temporary, but that depends on the lifetime of the &None
temporary, and since that temporary isn't actually stored in a let
(the exception to the rule about temporaries lasting until the end of the statement), its lifetime is less than the lifetime of cmd
and you get a lifetime error.
The direct struct statements work, because the let
lifetime applies to the struct and its members.
The fact that it doesn't work for Some
(an enum) seems like a bug to me (or at least a missing feature).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With