So the following is a version of the above code with visualisation of lifetime added
fn main() {
--let str = format!("Number {} is the answer", 42);
|
| --let mut arr : Vec<&str> = Vec::new();
| |
| | arr.push("abcd"); // okay cause constant strings are 'static
| |
| | arr.push(&str); // okay cause str lives longer than arr
| |
| | --let str2 = format!("Number {} is better actually", 43);
| | |
| | | arr.push(&str2); // not okay cause str2 lives shorter than arr
| | |
| | | // not okay cause the string is dropped after the expression completes
| | | arr.push(&format!("What about this number {}", 44));
| | v -- end of life for str2
| v -- end of life for arr
v -- end of life for str
}
So from purely theoretical point of view, or even when trying to formalise the lifetime system in logic, there doesn't seem to be any need for enforcing the ordering when things are in the same scope, and this would be right if we are in a managed language(e.g. OCaml, JS, Python).
But since Rust is not a managed language, and since we are allocating things on stack[1], this means the first delcared object will be allocated on stack first, and intuitively must have a longer lifetime than whatever follows, and so on.
[1] Actually this is a bit tricky here, since the content of String
and Vec
are heap allocated, but the handles(the values that arr
, str
and str2
actually hold) are still stack allocated, but they share the same lifetime. Think of a 2-layered struct, where one struct is stack allocated and points to the other struct which is heap allocated, but the lifetime of both struct are tied together, i.e. when the handle is dropped, the heap allocated struct is dropped as well.
TL;DR the heap content shares the exact same lifetime as the stack allocated content, so we may as well just look at the stack exclusively.
The stack view(assuming the stack builds upwards, doesn't matter in practice, but clarifying just for the visualisation) would look like
|-----------------|
| str2 |
|-----------------|
| arr |
|-----------------|
| str |
|-----------------|
| ... |
So intuitively, when we pop the stack content, we pop str2 first, then arr, then str(reverse order of allocation), and thus str2 has shorter lifetime than arr.