I'm new to Rust and like many finding lifetimes quite hard to get the hang of. I get the basics, but I can't quite fathom how to make this work.
I'm trying to implement an abstract data structure that holds a collection of records. One requirement is that the collection of records referenced by the data structure is represented as an Iterator
, because at times the records will be read from disk, at other times they'll come from memory, and at other times somewhere like a cache. The data structure itself doesn't care how the records are returned. It simply needs to be able to iterate over them and filter/map them etc.
My actual code is more involved than this, but I've distilled this down as much as possible to illustrate the issue I'm hitting.
Let's say I have a type Record
. It is not important what that is. If I have a Vec<Record>
called records
, then I can get an iterator over &Record
instances, using records.iter()
right? That's exactly what I need to store in a struct field, except that it needs to be abstract and not tied specifically to the implementation of Vec<T>
.
I have tried to define a trait as such:
trait RecordIterator: Iterator<Item = &Record> {}
And the struct that holds trait objects of this type:
struct RecordSet {
records_iter: Box<dyn RecordIterator>,
}
Of course this doesn't compile because I need to specify the lifetimes. The compiler suggests using higher rank lifetimes, so:
trait RecordIterator: for<'a> Iterator<Item = &'a Record> {}
impl<T> RecordIterator for T where T: for<'a> Iterator<Item = &'a Record> {}
But this gives me an error:
Compiling playground v0.0.1 (/playground)
error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
--> src/main.rs:3:40
|
3 | trait RecordIterator: for<'a> Iterator<Item = &'a Record> {}
| ^^^^^^^^^^^^^^^^^
error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
--> src/main.rs:5:56
|
5 | impl<T> RecordIterator for T where T: for<'a> Iterator<Item = &'a Record> {}
| ^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0582`.
error: could not compile `playground` due to 2 previous errors
Here is a link to the playground containing this code.
What do I need to do to store this kind of Iterator in the struct (as long as it is valid)? I'm also happy to avoid using Vec<T>::iter()
entirely and construct a new Iterator that basically does the same thing but meets the compiler's expectations if that is necessary.