Hi there,
I am still new to Rust and while I think I understand lifetimes, I still struggle on occasions. Like this one. I am trying to do something seemingly simple here. I got it to work using the compiler errors (which are very good) as a guide, but I would like to understand what I have actually done here. I would much appreciate if someone could talk me though this. So here is the code in question:
pub struct EntityImporter<'a, 'b> {
repositories: &'a Vec<Repository>,
entity_pool: &'b EntityPool,
}
impl EntityImporter {
pub fn new(repos: &Vec<Repository>, pool: &EntityPool) -> EntityImporter {
EntityImporter {
repositories: repos,
entity_pool: pool,
}
}
}
The compiler tells me explicit lifetime required in the type of repos; lifetime 'static required and explicit lifetime required in the type of pool; lifetime 'static required. Interesting. I change the code to
impl EntityImporter {
pub fn new(repos: &'static Vec<Repository>, pool: &'static EntityPool) -> EntityImporter {
EntityImporter {
repositories: repos,
entity_pool: pool,
}
}
}
...and the error goes away.
Q1: Why is a static lifetime required here? What do the 'static lifetimes mean here? I understand they don't mean "this reference will live as long as the program" (there are various articles explaining that to be a misconception), but I don't understand what it actually means. I make the suggested change.
pub fn new(repos: &'static Vec<Repository>, pool: &'static EntityPool) -> EntityImporter {...}
Now, I am still left with missing lifetime specifiers; expected 2 lifetime parameters; help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from repos or pool.
Q2: I guess, that makes sense. I am thinking I need to tie the lifetime of the resulting EntityImporter to the two parameters. So, I change them to also be static, do I? Is that the right thing to do? Or should I have gone for some non-static lifetimes, e.g. 'x and 'y? (See the PS down the bottom).
pub fn new(repos: &'static Vec<Repository>, pool: &'static EntityPool) -> EntityImporter<'static, 'static> {...}
That leaves me with implicit elided lifetime not allowed here; help: indicate the anonymous lifetimes: <'_, '_> on the impl EntityImporter... line. I follow the suggestion and all is working.
Q3: However, why is the compiler happy with anonymous lifetimes here? Why do I not have to make them static? Or explicit (see below).
PS: This also works with non-static lifetimes. As I said, I still don't understand what the 'static lifetimes actually mean, so I am having a hard time decided what is right here (I used 'x and 'y here just to make it clear that they are nothing to do with the lifetimes in the struct itself.)
impl<'x, 'y> EntityImporter<'_, '_> {
pub fn new(repos: &'x Vec<Repository>, pool: &'y EntityPool) -> EntityImporter<'x, 'y> {
EntityImporter {
repositories: repos,
entity_pool: pool,
}
}
}