// This function takes two string slices and returns the longer one. // The lifetime parameter `'a` ensures that the returned reference // lives at least as long as both input references. fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } fn main() { let string1 = String::from("long string is long"); let result_outer; // Declare result_outer outside the inner scope { // Inner scope for string2 let string2 = String::from("xyz"); // The return value `result_inner` will have a lifetime limited by the shorter of string1 and string2. // In this case, it will be limited by string2's scope. let result_inner = longest(string1.as_str(), string2.as_str()); println!("Inside scope: The longest string is '{}'", result_inner); // If we tried to assign `result_inner` to `result_outer` here, // it would be a compile-time error because `result_outer` might outlive `string2`. // result_outer = result_inner; // Uncommenting this line causes a compile error! // error[E0597]: `string2` does not live long enough } // string2 goes out of scope here. // If `result_outer` was assigned `result_inner`, printing it here would be a use-after-free, // which the Rust compiler prevents thanks to lifetime analysis. // println!("Outside scope: The longest string is '{}'", result_outer); // This would be a compile-time error if assigned! let string3 = String::from("another long string"); let result_valid = longest(string1.as_str(), string3.as_str()); println!("Both live long enough: The longest string is '{}'", result_valid); }