Hi there,
I am having trouble making the code below work. I have created something very close to a minimum example; playground can be found here:
The idea of the code is that there are a bunch of Entity classes that all get deserialised from disk by serde; Unit being one example. The entities are then added to an EntityPool and now the Entity has to be informed about which EntityPool it lives in (so it can look up other adjacent Entities in the same pool later).
So, that means that the Entities need a reference to the EntityPool. I understand that storing references in a struct is not great (someone on this forum has pulled me up on this before and I have taken that to heart). However, in this case I cannot see the alternative; clearly I cannot clone()
the EntityPool as that would be defeating its purpose.
So, I sprinkled some 'a
lifetime specifiers over the code and things improved, but I cannot figure out how to make this actually work. I am left with
error[E0308]: method not compatible with trait
--> src/main.rs:22:5
|
22 | fn init(&mut self, pool: &'a EntityPool) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&mut Unit<'a>, &'a EntityPool)`
found fn pointer `fn(&mut Unit<'a>, &'a EntityPool)`
...which makes little sense to me. My feeling is that some of the 'a
lifetime specifiers refer to the same thing while others do not. Could somebody please have a look at it? Here is the code:
use serde::Deserialize;
use serde_json;
/// EntityPool
pub struct EntityPool {
// implementation omitted
}
pub trait Entity {
fn init<'a>(&mut self, pool: &'a EntityPool);
}
#[derive(Deserialize)]
pub struct Unit<'a> {
#[serde(skip)]
pool: Option<&'a EntityPool>,
key: String,
name: String,
description: Option<String>,
}
impl<'a> Entity for Unit<'a> {
fn init(&mut self, pool: &'a EntityPool) {
self.pool = Some(pool);
}
}
fn main() {
let ep = EntityPool {};
let v = r#"
{
"key": "m",
"name": "millimeter",
"description": "some really small distance"
}
"#;
let mut unit: Unit = serde_json::from_str::<Unit>(v).unwrap();
// ep.add(unit); -- omitted
unit.init(&ep);
}
More generally, I have reread the chapter in the book on lifetimes and all seems simple enough. It seems to be those complex cases that I cannot find good explanations for. For example what does a lifetime specifier on an impl
, e.g. impl<'a>...
actually mean? Could someone maybe point me to something I could read to fill that gap in my knowledge. Again, thank you for your generous time.