I am learning Rust and facing a compilation issue. I simplified my code (so it does not make any sense as it is right now) to post my problem here.
I have a Parent structure filled with a ChildWrapper and a Vec<&Child>. But the compiler won't let me set the reference, as the created reference would not necessarily outlive its content. To my eyes setting lifetimes here (pub fn get<'a>(&'a self) -> &'a Child {) should reassure the compiler the ref will live long enough... but, nah.
If I take ChildWrapper out of Parent I can make it work but still, I don't understand what is not ok in my code.
struct Child {
e: bool,
}
impl Child {
pub fn new() -> Child {
Child { e: true }
}
}
struct ChildWrapper {
child: Child,
}
impl ChildWrapper {
pub fn new() -> ChildWrapper {
ChildWrapper { child: Child::new() }
}
pub fn get<'a>(&'a self) -> &'a Child {
&self.child
}
}
struct Parent<'a> {
child_ref: Vec<&'a Child>,
wrapper: ChildWrapper,
}
impl<'a> Parent<'a> {
pub fn new() -> Parent<'a> {
Parent {
child_ref : Vec::new(),
wrapper: ChildWrapper::new(),
}
}
pub fn set_child_ref(&mut self) {
self.child_ref.push(self.wrapper.get());
}
}
fn main() {
let mut parent = Parent::new();
parent.set_child_ref();
}
And this is the error I am getting :
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:41:36
|
41 | self.child_ref.push(self.wrapper.get());
| ^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 40:2...
--> src/main.rs:40:2
|
40 | pub fn set_child_ref(&mut self) {
| _____^
41 | | self.child_ref.push(self.wrapper.get());
42 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:41:23
|
41 | self.child_ref.push(self.wrapper.get());
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 32:6...
--> src/main.rs:32:6
|
32 | impl<'a> Parent<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:41:23
|
41 | self.child_ref.push(self.wrapper.get());
| ^^^^^^^^^^^^^^^^^^
I know how to workaround the issue, and it probably is the sign of a bad design (or maybe not ?) but I am looking for an explanation and eventually a solution using this same architecture...
Like how to explicitly set the correct lifetime for self.wrapper.get() ?
Thank you!
pub fn set_child_ref(&mut self) {=>pub fn set_child_ref(&'a mut self) {I am not sure why but this lifetime had to be explicit. Feel free to give further explanations ! - gpoblon&'a mut self, when'ais a parameter ofSelf, is almost always a mistake. In this case it works, but you have made it impossible to do anything else withparent, because it's now permanently (and uniquely) borrowed. The best solution to this kind of problem is to avoid self-referential structs. Why can't I store a value and a reference to that value in the same struct? has further explanation and suggestions. - trentcl