0

I'm trying to write an iterator over data which is lazily fetched from the local disk:

struct Data {}

struct DataDecoder {}

impl DataDecoder {
    fn decode_data(&mut self) -> Option<Vec<Data>> {
        // in reality does some IO, might fail
        Some(vec![Data {}])
    }

    fn iter(&self) -> DataIterator {
        DataIterator {
            decoder: self,
            data: None,
            idx: 0,
        }
    }
}

struct DataIterator<'a> {
    decoder: &'a DataDecoder,
    data: Option<Vec<Data>>,
    idx: usize,
}

impl<'a> Iterator for DataIterator<'a> {
    type Item = &'a Data;

    fn next(&mut self) -> Option<Self::Item> {
        if self.data.is_none() {
            self.data = self.decoder.decode_data();
        }
        let ret = match self.data {
            None => None,
            Some(ref data) => data.get(self.idx),
        };
        self.idx += 1;
        ret
    }
}

I'm getting a compilation error:

error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
  --> src/lib.rs:35:18
   |
35 |             Some(ref data) => data.get(self.idx),
   |                  ^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 29:5...
  --> src/lib.rs:29:5
   |
29 | /     fn next(&mut self) -> Option<Self::Item> {
30 | |         if self.data.is_none() {
31 | |             self.data = self.decoder.decode_data();
32 | |         }
...  |
38 | |         ret
39 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:35:18
   |
35 |             Some(ref data) => data.get(self.idx),
   |                  ^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 26:6...
  --> src/lib.rs:26:6
   |
26 | impl<'a> Iterator for DataIterator<'a> {
   |      ^^
   = note: ...so that the types are compatible:
           expected std::iter::Iterator
              found std::iter::Iterator

What do I need to change?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Shmoopy
  • 5,334
  • 4
  • 36
  • 72
  • AFAICT, the compiler tries to tell you that items returned by decoder may have a shorter lifetime than `'a`, so references to them can't be safely put to the `data` vector. Either guarantee the lifetime of the decoded objects, or make copies, or maybe "move" the data, not "borrow" it. – 9000 Dec 26 '18 at 17:36
  • 1
    This is the "streaming iterator" problem, a recurring issue with the way Rust's iterators are defined. See especially the comments by "le_me" in my linked dupe suggestion for a bit of explanation. – Sebastian Redl Dec 26 '18 at 19:07

0 Answers0