This is not true, the associated type Iterator::Item can absolutely be a reference. I think you are confusing this with the fact that it can't be a reference into data that is owned by the iterator, because the signature of Iterator::next() lacks the required lifetime annotations, i.e. it's not fn next(&'a mut self) -> Option<Self::Item> where Self::Item: 'a.
But .iter() methods, by convention, return an iterator that only borrows its data from the parent collection. Therefore this is perfectly fine. The fully expanded signature in this case is:
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
/* ... */
}
So, the Item type here is indeed a reference. As @H2CO3 points out, its lifetime comes from the original slice. That lifetime is collected from the iter method’s self argument and independent from the lifetime of Iter::next’s self reference.
struct MySliceIter<'a,T> {
next_idx: usize,
content: &'a [T],
}
impl<'a,T> Iterator for MySliceIter<'a,T> {
type Item = &'a T;
fn next(&mut self)->Option<&'a T> {
self.content.get(self.next_idx)
.map(|x| { self.next_idx += 1; x })
}
}
fn main() {
let v: Vec<usize> = vec![3,1,4,1,5,9,2,8];
let my_iter = MySliceIter {
next_idx: 0,
content: &*v
};
// enumerate is here to demonstrate that the reference is
// inside the iteration value, and not an artifact of for_each
my_iter.enumerate()
.for_each(|x:(usize, &usize)| { dbg!(x); });
}
In our examples the associated type Iterator::Item is a fixed type within the context of the implementation -- for example the lifetimes of ColorIter<'a> and (&'a str, f32) must be the same. And thus the lifetime of the items returned from next() must be the same as well.
With GATs you could have an Iterator::Item with a generic lifetime, which could be determined at each call site to next(). This would allow "lending iterators", which is the motivating example for GATs. (Sometimes these are also called "streaming iterators", especially before async was implemented. But don't confuse them with async streams.)