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'a
is 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