Reputation: 13363
I have abstracted my problem inside the following code:
struct List<'a> {
attr: &'a String
}
impl<'a> List<'a> {
fn new() -> List<'a> {
let my_attr = "Something";
List {
attr: &my_attr.to_string()
}
}
}
fn main() {
List::new();
}
It yields some notices and fails compiling claiming that the borrowed value (my_attr) doesn't live long enough.
It makes sense, so for instance the following does indeed compile:
struct List<'a> {
attr: &'a String
}
impl<'a> List<'a> {
fn new(my_attr: &'a String) -> List<'a> {
List {
attr: my_attr
}
}
}
fn main() {
let my_attr = "Something".to_string();
List::new(&my_attr);
}
However, I like the first form more, especially from an encapsulation stand point.
Is it possible to create and also assign a reference to a value from within the new method (as per the failing example)?
Upvotes: 0
Views: 98
Reputation: 29941
The issue here is that a &'a String
is a borrowed value - that is, it is a reference to a value that is stored elsewhere. On your first example, that "elsewhere" is the new
function stack, and on the second it's main
's stack.
You don't get an error on the second case because main
's lifetime is bigger than your List
's lifetime - that is, the List
will die before main
finishes. That is not the case of your first scenario, where the List
is returned by new
, and thus the reference is invalid.
The solution here is to make List
own its String
, instead of just taking a reference to it. This way, List
's lifetime isn't linked to anything else.
struct List {
attr: String,
}
impl List {
fn new() -> List {
let my_attr = "Something";
List {
attr: my_attr.to_string()
}
}
}
Upvotes: 2