1

Need help to make this work. I thought clone() would make a deep copy of my string. Then getting the literal-string of it would just be a value ... not linked to any variable?

fn main() {
    let mut keep_vec: Vec<&str> = vec![];

    let new_string = "New String".to_string();

    // create a new string inside an expression
    // and push it into the keep_vec
    {
        let second_string = "Second String".to_string();

        /* created this after I got ERROR:
        
        temporary value dropped while borrowed E0716 
        creates a temporary which is freed while still 
        in use Note: consider using a `let` binding to 
        create a longer lived value
         */
        
        let string_clone = second_string.clone();

        /* now getting this ERROR:
        
        `string_clone` does not live long enough E0597 
        borrowed value does not live long enough
         */
        
        keep_vec.push(string_clone.as_str());
        
    }

    keep_vec.push(&*new_string);
}

Here is a link to the Rust Playground.

Robert
  • 131
  • 1
  • 7
  • Also, it may help you to understand better your error to see what exactly causes it on [this example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=df457572abc92a9a06bf4ed5c6f2da76). It's not the same compiler error, but it's the same idea. – jthulhu Aug 28 '22 at 15:47
  • `&str` is not a string literal, string literals are `&'static str`, what you had have no static lifetime – Ömer Erden Aug 28 '22 at 15:53
  • 2
    You seem to think that a value such as `"hello"` and `"hello".to_string().as_str()` have the same type. But they have not: the first one is a `&'static str` that lives forever while the second is a `&'a str` that lives as long as the intermediate `String`. In your case `string_clone` has a limited lifetime and that is lifetime of `string_clone.as_str()` too. – rodrigo Aug 28 '22 at 15:54
  • One commenter suggested to give the `sting_clone` a longer life by putting it outside the expression. However, the issue is that the variable is being borrowed at `keep_vec.push(string_clone.as_str());` and thus, if I have many more expressions ... I would have to create many of those variable to all be there for the same reason....Isn't there a way to give a value to the vector without any "strings attached"? – Robert Aug 28 '22 at 16:40
  • I guess the problem is not necessary the LIFETIME of a string rather how to decouple the string-literal from a variable and use(burn) it in a function as a plain value with "no strings attached". Here is another [playground example](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=5a05640a18e823e031fed85fad571a89) ... I will change the Question to better reflect what I am looking for ... I hope this is ok ?! – Robert Aug 28 '22 at 16:58
  • @Robert Is this what you need? https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=b39d4609445fd54c448fbd0e39aae4d4 – Finomnis Aug 28 '22 at 17:16
  • Please check this [example](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=fdd5c474b6699924f7379c33b9589804), it will prove that it is a lifetime issue, borrowed objects can stay because the original ones are still alive – Ömer Erden Aug 28 '22 at 17:18
  • The entire confusion in the question comes (I think) from the fact that OP doesn't sufficiently understand the difference between `String` and `str`, so I would agree to mark this a duplicate. – Finomnis Aug 28 '22 at 17:51

1 Answers1

2

&str is not an owned type. It is a reference to a string stored somewhere else.

String is the owned type that actually contains the data.

fn main() {
    let mut keep_vec: Vec<String> = vec![];

    let new_string = "New String".to_string();

    // create a new string inside an expression
    // and push it into the keep_vec
    {
        let second_string = "Second String".to_string();
        keep_vec.push(second_string);
    }

    keep_vec.push(new_string);
}

There is no need to clone() your strings. to_string() already creates a String which owns its content. You can simply move it into the vector.

Your problem was that Vec<&str> cannot hold any data, because it's a vector of references. If you want a vector that actually holds its string values, it needs to be a Vec<String>.


getting the literal-string of it would just be a value

I think you misunderstand what a "string literal" is.

Here a quick recap, although this is already mentioned in the duplicate:

  • String - owns its content, doesn't borrow anything. Can get created via "bla".to_string().
  • &str - reference to (part of) another string, doesn't own its content. The data it references has to outlive it.
  • &'static str - A string literal. A reference to a string that is stored in const static memory, is immutable and valid throughout the entire program. Like "bla". (Disclaimer: other things that are not string literals could also be &'static str; this is oversimplified to make it easier to digest for Rust beginners)
Finomnis
  • 18,094
  • 1
  • 20
  • 27
  • ... and as simple as that ... `Vec` ... did the trick :) Thanks to @Finomnis and everyone else to help me better understand and solve this issue. – Robert Aug 28 '22 at 17:39
  • `&'static str` doesn't always mean it is a literal, you can [leak](https://stackoverflow.com/a/30527289) dynamically created string into memory and represent it as `&'static str` . but yes String literals are `&'static str` – Ömer Erden Aug 28 '22 at 17:47
  • 1
    Added a disclaimer to make that clear that this is a simplified answer. – Finomnis Aug 28 '22 at 17:49