I can't understand why I can't return a reference from iterator implementation

I have a Struct that returns data continuously similar to Cycle and it has a method called next that returns a Option<&T> When I try to implement Iterator trait however I get lifetime errors.
I just cannot understand how am I supposed to explain Item is a reference that will live as long as &mut self will.

pub struct CachedDataProvider<T>
{
	data: Vec<T>,
	curr_index: usize,
}

impl<T> CachedDataProvider<T>
{
	pub fn new(data: Vec<T>) -> Self //{{{
	{
		//{{{
		Self {
			data,
			curr_index: 0,
		}
	} //}}}
	pub fn remove(&mut self, cb: impl Fn(&T) -> bool)
	{
		//{{{
		if let Some(i) = self
			.data
			.iter()
			.enumerate()
			.find_map(|(i, v)| cb(v).then(|| i))
		{
			self.data.remove(i);
			if self.curr_index > i {
				self.curr_index -= 1;
			}
		};
	} //}}}
	pub fn next(&mut self) -> Option<&T>
	{
		//{{{
		let len = self.data.len();
		if len == 0 {
			return None;
		}
		let item = self.data.get(self.curr_index);
		self.curr_index = (self.curr_index + 1) % len;
		item
	} //}}}}}}
}

impl<T> Iterator for CachedDataProvider<T>
{
	type Item = &'a T; //I cant find a way to explain to compiler that T will live 'a much since it is borrowed from self

	fn next<'a>(&'a mut self) -> Option<&Self::Item>
	{
		CachedDataProvider::next(self)
	}
}

Iterator::next is not allowed to return a reference to data owned by the iterator itself. You'll have to use a different approach.

1 Like

You can just use while let instead of for:

fn f(mut cdp: CachedDataProvider<String>) {
    while let Some(thing) = cdp.next() {
        println!("{}", thing);
    }
}

But you lose the convenience of Iterator trait bounds, sadly.

What you really want is a lending iterator, but you won't be able to define one on stable until GATs land.

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.