Let's take a closer look at the signature for longest:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str
What this means is that for a given lifetime 'a, both arguments need to last at least for the length of that lifetime (or longer, which doesn't really matter since you can safely shorten any lifetime in this case without any particular difference) and the return value also lives as long as that lifetime, because the return value comes from one of the arguments and therefore "inherits" the lifetime.
The sole reason for that is that at compile time, you can't really be sure whether x or y will be returned when compiling the function, so the compiler has to assume that either can be returned. Since you've bound both of them with the same lifetime (x, y and the return value have to live at least for the duration of 'a), the resulting lifetime of 'a is the smallest one. Now let's examine the usage of the function:
let long;
let str1 = "12345678".to_string();
{
let str2 = "123".to_string();
long = longest(&str1, &str2);
}
You have two lifetimes here, the one outside the braces (the main() body lifetime) and the lifetime inside the braces (since everything between the braces is destroyed after the closing brace). Because you're storing the strings as String by using .to_string() (owned strings) rather than &'static str (borrowed string literals stored in the program executable file), the string data gets destroyed as soon as it leaves the scope, which, in the case of str2, is the brace scope. The lifetime of str2 ends before the lifetime of str1, therefore, the lifetime of the return value comes from str2 rather than str1.
You then try to store the return value into long — a variable outside the inner brace scope, i.e. into a variable with a lifetime of the main() body rather than the scope. But since the lifetime of str2 restricts the lifetime of the return value for longest in this situation, the return value of longest doesn't live after the braced scope — the owned string you used to store str2 is dropped at the end of the braced scope, releasing resources required to store it, i.e. from a memory safety standpoint it no longer exists.
If you try this, however, everything works fine:
let long;
let str1 = "12345678";
{
let str2 = "123";
long = longest(str1, str2);
}
println!("the longest string is: {}", long);
But why? Remember what I said about how you stored the strings, more specifically, what I said about borrowed string literals which are stored in the executable file. These have a 'static lifetime, which means the entire duration of the program's runtime existence. This means that &'static to anything (not just str) always lives long enough, since now you're referring to memory space inside the executable file (allocated at compile time) rather than a resource on the heap managed by String and dropped when the braced scope ends. You're no longer dealing with a managed resource, you're dealing with a resource managed at compile time, and that pleases the borrow checker by eliminating possible issues with its duration of life, since it's always 'static.
'abe the lifetime parameter of the first parameter always? - Guerlando OCs'afor bothxandywhen you definelongest, you specify that'ais the longest lifetime for which bothxandyare guaranteed to live. You're right to do so. If you had simply removed'ain your declaration, Rust would have basically inferred the same. I'm not sure what you mean by "first parameter", though. - Yoric