Confused by lifetimes


#1

Hello,

I’m quite new to Rust and still trying to figure out some of these basics.

I’m getting an error when I try to create a Vec of &str, then return it. The specific error is:
error: missing lifetime specifier [E0106]
pub fn get_peers<'a>() -> &'a Vec<&str> {
^~~~ is pointing at the & in ‘&str’

I’m doing much more than this but when I trim out the unrelated parts the code is:

pub fn get_peers<'a>() -> &'a Vec<&str> {
    let mut peer_array: Vec<&str> = Vec::new();
    peer_array;
}

I’ve spent a number of hours messing around with this, sure someone else who knows what they are doing immediately see the error?

Thank you!


#2

The compiler is complaining about a missing lifetime specifier for &str. Your saying your function returns a vector of strings references, but not saying what are the liftime of those references.

In your case, &str generally have a static lifetime (unless they are created from a String), so something that would compile and probably work for you is:

pub fn get_peers<'a>() -> &'a Vec<&str>

Alternatively, you could use the same lifetime specifier as you are using for the borrow of Vec:

pub fn get_peers<'a>() -> &'a Vec<&'a str>

Which is basically saying that the string borrows inside the Vec have to last as long as the Vec itself.

Finally, you probably don’t want to return a reference to a Vec, but rather a Vec by itself:

pub fn get_peers() -> Vec<&'static str>

Here’s a full example: (http://is.gd/oWUxxc)

pub fn get_peers() -> Vec<&'static str> {
    let mut peer_array: Vec<&str> = Vec::new();
    peer_array
}

fn main() {
    let mut foo = get_peers();
    foo.push("hello");
}

#3

Side-note, when you want to return a value, don’t use a semicolon. Terminating the statement prevents the value from passing through. Or you can explicitly say return peer_array; and a semicolon is fine.


#4

I appreciate it both of you! alevy, you’re solution did indeed fix it and cuviper fixed the next issue which I wasn’t anticipating.

Ok, having an issue within the same part of code, and not sure why, if I’m able to call s using a print statement immediately before this line, then it must be alive right? I only passed it into read_to_string as a borrow and otherwise haven’t touched it. So why does it cut off on that line?

This is the error:

src\network.rs:33:27: 33:28 error: `s` does not live long enough
src\network.rs:33             let peer_vec= s.split("\n");
                                            ^
note: reference must be valid for the static lifetime...
src\network.rs:27:31: 47:2 note: ...but borrowed value is only valid for the block suffix following statement 3 at 27:30
src\network.rs:27     let mut s = String::new();
src\network.rs:28     let mut peer_array: Vec<&str> = Vec::new();
src\network.rs:29     match file.read_to_string(&mut s) {
src\network.rs:30         Err(why)=>panic!("Couldn't read {}: {}", display, Error::description(&why)),
src\network.rs:31         Ok(_)=> {
src\network.rs:32             print!("{}",s);

This is all taking place within “pub fn get_peers() -> Vec<&'static str> {”


#5

It would help if you shared a complete example, on Rust Playground for instance.

From what context is in your error message, I’m guessing that you insert values from peer_vec into peer_array, and then return that? Those &str slices only live as long as the String they came from, but 'static means they must live forever. A static string is usually a literal constant.

For any dynamically generated data, someone has to own that memory. That’s the first question for you to answer about lifetimes, “who owns this?” You could return Vec<String> so full ownership is passed back to the caller.

Also, it’s probably faster to use split() or lines() on a BufReader, rather than a full intermediate string.


#6

Ok, I think I see it. Will probably keep as String for now but going to dive into that chapter to get more comfortable with str vs String.

That being said, I decided to try to play with BufReader, and am running into all sorts of issues. All I want to do is read the lines from the file, and store them into an array and output it from the function.

I did go to Rust playground (which is awesome!) and here is the example:
http://is.gd/QdD6dm

I’ve tried a few different things and having trouble finding a good example.

Thanks again.

Edit: Believe I got Bufreader working, was easier than I thought. So for now I’m good, again, I appreciate the help.