Hi fellow rustacean! I try to implement the Iterator trait for a custom struct Foo, which owns a vector of Rc<RefCell<Bar>> and I want to emit a std::cell::Ref to each of Bar as the Item.
I tried to specify the lifetime of Ref with '_, but the compiler complains that '_ is not allowed here.
use std::cell::{Ref, RefCell};
use std::rc::Rc;
struct Bar{}
struct Foo{
data: Vec<Rc<RefCell<Bar>>>
}
impl Iterator for Foo{
// how can i correctly specify Item here ?
type Item = Ref<'_, Bar>;
fn next(&mut self) -> Option<Self::Item>{
todo!()
}
}
// the lifetime relationship i wanna express is like the following
fn next(&'a mut self) -> Option<Ref<'a, Bar>>
That's classic “something people want but wouldn't get any time soon”.
What you are describing is classic LendingIterator which even sprouted creation of GAT's which were stabilized in rust 1.65.
But, unfortunately, the normal Iterator is not lending and turning it into lending one would be a backward-incompatible change thus no, that wouldn't work.
the LendingIterator is nowhere near, the traditional way is to create a separate type for the iterator, which typically holds a reference to the actual container type, plus some mutable states as the "cursor".
in this case, because your container is just a wrapper of Vec, your iterator type can be implemented as a wrapper over the iterator type of Vec, i.e. std::slice::Iter<'_>, something like:
My naming is a little bit misleading here. My actual use case is little bit complex than this. I have another more complex data structure say Baz, when about to iterate Baz, I will selectively clone some Rc<RefCell<Bar>> into a Vec. There is actually no struct owns the Vec<Rc<RefCell<Bar>>>. Can i create this Vec on the fly when iterating and store it into BazIter? It's better to name Foo as BazIter.
// create on the fly when iterating Baz
struct Baz{
fn iter(&self) -> BazIter{
BazIter {
data: // selectively clone some Rc
}
}
}
struct BazIter{
data: Vec<Rc<RefCell<Bar>>>,
cursor: usize
}
impl Iterator for BazIter{
// how to address this lifetime?
type Item = Ref<'a, Bar>;
}