I’m having some issue figuring out a lifetime error I’m getting when trying to implement the Iterator
trait on a struct internally storing a reference. I have simplified the code a bit, hopefully I haven’t omitted something important, but it looks like this:
pub trait QueryData {
type Item<'a>;
fn fetch<'r>(entity_registry: &'r mut EntityRegistry, idx1: usize, idx2: usize) -> Self::Item<'r>;
}
pub struct Query<'a, D>
where
D: QueryData,
{
entity_registry: &'a mut EntityRegistry,
idx1: usize,
idx2: usize,
_pd: std::marker::PhantomData<D>,
}
impl<'a, D> Iterator for Query<'a, D>
where
D: QueryData,
{
type Item = D::Item<'a>;
fn next(&mut self) -> Option<Self::Item> {
// Bunch of logic here to update the indices...
return Some(D::fetch(self.entity_registry, self.idx1, self.idx2));
}
}
This fails to compile with the error:
172 | impl<'a, D> Iterator for Query<'a, D>
| -- lifetime `'a` defined here
...
178 | fn next(&mut self) -> Option<Self::Item> {
| - let's call the lifetime of this reference `'1`
...
201 | break Some(D::fetch(self.entity_registry, self.idx1, self.idx2));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
I’m a bit puzzled because in my mind lifetimes should be properly setup:
entity_registry
has lifetime'a
, by the definition of theQuery
struct.Iterator::Item
also has lifetime'a
, by the implementation ofIterator
.QueryData::fetch
requiresentity_registry
and the returnedItem
to have the same lifetime.
The moment I’m calling D::fetch
within next
, I would expect the compiler to figure out that self.entity_registry
has lifetime 'a
, by definition, which matches the lifetime of the returned data.
Clearly I’m missing something though. 😀 Is there some hidden lifetime issue, or maybe I’m just forgetting to annotate lifetimes somewhere?