I'm new to Rust's lifetimes concept and can't wrap my head around a particular piece of code. I've been working with Rust's SDL bindings and its Texture/TextureCreator classes and the problem basically boils down to the following scheme:
struct Creator;
impl Creator {
fn create(&self) -> Creature {
Creature { creator: &self }
}
}
struct Creature<'a> {
creator: &'a Creator,
}
struct MyStruct<'a> {
creator: Creator,
creatures: Vec<Creature<'a>>,
}
impl<'a> MyStruct<'a> {
fn new() -> MyStruct<'a> {
MyStruct {
creatures: Vec::new(),
creator: Creator,
}
}
fn create(&mut self) {
let new_creature = self.creator.create();
self.creatures.push(new_creature);
}
}
fn main() {
let mut my_struct = MyStruct::new();
my_struct.create();
}
The actual problem lies inside MyStruct::create
method. If I try to compile the above code I get:
error[E0495]: cannot infer an appropriate lifetime for autoref due to con
flicting requirements
--> src/main.rs:27:41
|
27 | let new_creature = self.creator.create();
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 define
d on the method body at 26:5...
--> src/main.rs:26:5
|
26 | / fn create(&mut self) {
27 | | let new_creature = self.creator.create();
28 | | self.creatures.push(new_creature);
29 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:27:28
|
27 | let new_creature = self.creator.create();
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on t
he impl at 18:6...
--> src/main.rs:18:6
|
18 | impl<'a> MyStruct<'a> {
| ^^
= note: ...so that the expression is assignable:
expected Creature<'a>
found Creature<'_>
The interesting thing is that when I comment out this line inside MyStruct::create
:
self.creatures.push(new_creature);
it compiles just fine.
My assumption is that it can lead to the following problem - a newly created new_creature
has a reference to the creator
which is owned by my_struct
. Now, if that new_creature
is then owned by the creatures
vector, I can't really call any method on my_struct
that borrows itself as mut
because at that point there will be:
- a reference to
creator
insidemy_struct
- a mutable reference to
my_struct
inside the method's body (and therefore tomy_struct.creator
)
However, this is how I see it from my point of view. From the compiler's standpoint it's about lifetimes and don't quite get it. So I have the two following questions:
- Why does the compiler complain about lifetimes in this case?
- How can I go about storing
Vec<Creature>
in a struct? Should I make sure that I don't keep bothCreator
andVec<Creature>
in the same struct to avoid the aforementioned issue?