0
fn get_str1<'a>() -> &'a str {
    let x = "hello";
    return x;
}

fn get_str2<'a>(str1: &str) -> &'a str {
    let x: &'a str = (str1.to_string() + "123").as_str();
    return x;
}

fn get_str3<'a>(str1: &str) -> &'a str {
    let tmp = str1.to_string() + "123";
    let x: &'a str = tmp.as_str();
    return x;
}

#[test]
fn lifetime_test() {
    println!("{}", get_str1());
    println!("{}", get_str2("hello"));
    println!("{}", get_str3("hello"))
}

When I call get_str1, it has no problem, but when I call get_str2, it has a compilation error:

error[E0597]: borrowed value does not live long enough
 --> src/main.rs:7:22
  |
7 |     let x: &'a str = (str1.to_string() + "123").as_str();
  |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^         - temporary value only lives until here
  |                      |
  |                      temporary value does not live long enough
  |
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 6:1...
 --> src/main.rs:6:1
  |
6 | fn get_str2<'a>(str1: &str) -> &'a str {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = note: consider using a `let` binding to increase its lifetime

When I call get_str3, it also has a compilation error:

error[E0597]: `tmp` does not live long enough
  --> src/main.rs:13:22
   |
13 |     let x: &'a str = tmp.as_str();
   |                      ^^^ borrowed value does not live long enough
14 |     return x;
15 | }
   | - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 11:1...
  --> src/main.rs:11:1
   |
11 | fn get_str3<'a>(str1: &str) -> &'a str {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Why do I get these errors and how do I fix get_str2 and get_str3?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
刘林欣
  • 123
  • 1
  • 6

1 Answers1

1

The first function works because the string has the 'static lifetime and will be promoted by the compiler.

As for the others..

fn get_str2<'a>(str1: &str) -> &'a str {
    let x = (str1.to_string() + "123").as_str();
    return x
}

This part: str1.to_string(), isn't returning a string slice... but a new instance of a String. This is basically the same as this:

let x = str1.to_string(); // this is of type String, and its lifetime is local to this function
let y = str1 + "123"; // This consumes str1 and appends a &str to it - thus the lifetime is still of the new String instance above
let z = y.as_str(); // This returns a reference to the local String instance

Reading each comment above, it becomes clear that you're actually trying to return a reference to a local String. You can't do this, because the String will be destroyed at the end of the function and the reference will be invalid.

This applies to your third function as well. You're returning a reference to a String instance that will be destroyed at the end of the function.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138