The Issue
I'm trying to implement an iterator that yields windows (i.e. slices) into a buffer owned by the iterator itself – for example, if the buffer contains [0, 1, 2, 3, 4, 5], the iterator might yield [0, 1, 2, 3], [2, 3], or [3, 4, 5]. Here's a minimal example (Playground):
struct Slicer<'a> {
full: Vec<u32>,
cur_slice: &'a mut [u32]
}
impl<'a> Slicer<'a> {
fn new() -> Slicer<'a> {
let mut full = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
Slicer {
full: full, // Is there a way to transfer ownership of `full` here?
cur_slice: full.as_mut_slice()
}
}
}
impl<'a> Iterator for Slicer<'a>
{
type Item = &'a [u32];
fn next(&mut self) -> Option<&'a [u32]> {
if self.cur_slice.len() != 0 {
// In the actual program, this is streaming new data into the
// buffer. This is just an example of modifying the slice.
let len = self.cur_slice.len();
self.cur_slice = self.cur_slice[..len - 1].as_mut();
Some(self.cur_slice) // Getting a lifetime error here…
} else {
None
}
}
}
fn main() {
let mut slicer = Slicer::new();
while let Some(x) = slicer.next() {
println!("{x:?}");
}
}
This results in two separate errors: error[E0515]: cannot return value referencing local variable `full` and error: lifetime may not live long enough. Full errors:
error[E0515]: cannot return value referencing local variable `full` --> src\main.rs:11:9 | 11 | / Slicer { 12 | | full: full, 13 | | cur_slice: full.as_mut_slice() | | ---- `full` is borrowed here 14 | | } | |_________^ returns a value referencing data owned by the current functionerror: lifetime may not live long enough --> src\main.rs:26:13 | 16 | impl<'a> Iterator for Slicer<'a> | -- lifetime `'a` defined here ... 20 | fn next(&mut self) -> Option<&'a [u32]> { | - let's call the lifetime of this reference `'1` ... 26 | Some(self.cur_slice) // Getting a lifetime error here… | ^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
Now, from what I understand, this counts as an iterator that refers to itself – which an Iterator is unable to do (because the signature of next doesn't include an explicit lifetime for &mut self – with fairly good reason, from what I understand). This appears to be a perfect use case for lending iterators (as mentioned in this previous StackOverflow answer, and in fact, a window iterator is the primary example in the docs), but I attempted an implementation using a lending iterator, and was presented with exactly the same errors.
The Question
How does one fix this? Is there a way to make the lending iterator approach work? Is there a different composition that achieves the same effect?
(Note that I can't copy the data, as that would defeat the purpose of the iterator, which is meant to be a more ergonomic interface into parsing a particular file format with a lot of data.)
Iteratorfundamentally can't do this I don't see how adding that implementation is relevant here, if you add your attempt usingLendingIteratorwe can look at that and figure out where you went wrong. External resources like your gist are problematic if you don't include them within the post itself for several reasons.Iteratorfor your struct at all but add a separateIterstruct alltogether.fullhere?" → yes, that's what the code you comment on does…