I'm trying to implement Iterator
for one of my structs:
pub struct Node {
pub val: Vec<usize>,
}
pub struct NodeIter<'a, 'b> {
val: &'a Vec<usize>,
env: &'b mut Env,
index: usize,
}
impl<'a, 'b> Iterator for NodeIter<'a, 'b> {
type Item = &'b mut Obj;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.val.len() {
return Some(self.env.get_obj_at_mut(self.val[self.index]))
}
self.index += 1;
None
}
}
and upon compilation get the following error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src\core\nodes.rs:20:23
|
20 | Some(self.env.get_obj_at_mut(self.val[self.index]))
| ^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src\core\nodes.rs:19:13
|
19 | fn next(&mut self) -> Option<&'a mut Obj> {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src\core\nodes.rs:20:14
|
20 | Some(self.env.get_obj_at_mut(self.val[self.index]))
| ^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src\core\nodes.rs:16:6
|
16 | impl<'a> Iterator for NodeIter<'a> {
| ^^
note: ...so that the types are compatible
--> src\core\nodes.rs:20:9
|
20 | Some(self.env.get_obj_at_mut(self.val[self.index]))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Option<&'a mut Obj>`
found `Option<&mut Obj>`
I understood the issue to be that the &mut Obj
from get_obj_at_mut
(which returns a &mut Obj with a lifetime of 'b
, same as env
) might outlive &mut self
leaving a null reference in its place. The issue is that env
is bound by a mutable reference and may last beyond NodeIter
So I tried two options:
'b: 'c
:
impl<'a, 'b> NodeIter<'a, 'b> {
fn next_impl<'c>(&'c mut self) -> Option<&'b mut Obj> where 'b: 'c {
if self.index < self.val.len() {
return Some(self.env.get_obj_at_mut(self.val[self.index]))
}
self.index += 1;
None
}
}
this fails, stating that 'b
cannot outlive 'c
'c: 'b
impl<'a, 'b> NodeIter<'a, 'b> {
fn next_impl<'c>(&'c mut self) -> Option<&'b mut Obj> where 'c: 'b {
if self.index < self.val.len() {
return Some(self.env.get_obj_at_mut(self.val[self.index]))
}
self.index += 1;
None
}
}
this allowed next-impl
to successfully compile, but it cannot be called from next
due to the lifetime limitations
I know this might be similar to other questions about Rust lifetimes, but I haven't been able to figure out why 'b
can't outlive 'c
and more generally how to implement Iterator
I'm still new to Rust, so any help would be much appreciated
EDIT
pub fn get_obj_at_mut(&mut self, index: usize) -> &mut Obj {
&mut self.symbols[index]
}
this is in the impl
block for Env
, where symbols
is an owned Vec
of Obj