Fixed example:
fn main() {
let strA = "a".to_string();
let result;
{
let strB = "abc".to_string();
result = longest(&strA, &strB); // Will return strB
}
println!("The longest string is {}", result); // compile error
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
Now produces a compiler error as expected:
error[E0597]: `strB` does not live long enough
--> src/main.rs:7:33
|
7 | result = longest(&strA, &strB); // Will return strB
| ^^^^^ borrowed value does not live long enough
8 | }
| - `strB` dropped here while still borrowed
9 |
10 | println!("The longest string is {}", result); // result now point to strB!!
| ------ borrow later used here
playground
Rust was not "ignoring" the lifetimes of the string variables in your initial example. When you set a variable to a string literal that literal gets hardcoded into the executable binary and gets a 'static lifetime which means it's valid for the entire duration of the program. If we add explicit type annotations to your initial example it should become clear why it compiles and works:
fn main() {
let strA: &'static str = "a";
let result;
{
let strB: &'static str = "abc";
result = longest(&strA, &strB); // returns 'static str
}
println!("The longest string is {}", result); // prints result
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
However when we call to_string() on a string literal we create an owned and heap allocated String which lifetime's is non-static and is scoped to whatever block its in, hence making the change makes the program no longer compile as expected.