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:
&None
creates a temporary with a lifetime of the single line.Cmd::new
returns aCmd
that has the same lifetime. Then we have attempt to store that temporary in a variable withlet
.The Rust reference states:
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 alet
(the exception to the rule about temporaries lasting until the end of the statement), its lifetime is less than the lifetime ofcmd
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).