Reputation: 23
I've defined a struct which only has a slice of element of type T.
pub struct MyStruct<'a, T> {
slice: &'a mut [T],
}
I want to define an Iterator
for MyStruct
which yields a MyStruct
with a slice which has 10 elements.
impl<'a, E> Iterator for MyStruct<'a, E> {
type Item = MyStruct<'a, E>;
fn next(&mut self) -> Option<Self::Item> {
if self.slice.len() < 10 {
return None;
} else {
let (head, tail) = self.slice.split_at_mut(10);
self.slice = tail;
Some(MyStruct { slice: head })
}
}
}
But unfortunately I'm lifetime issues.
error: lifetime may not live long enough
--> src/lib.rs:12:32
|
5 | impl<'a, E> Iterator for MyStruct<'a, E> {
| -- lifetime `'a` defined here
...
8 | fn next(&mut self) -> Option<Self::Item> {
| - let's call the lifetime of this reference `'1`
...
12 | let (head, tail) = self.slice.split_at_mut(10);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
I'm not an expert in lifetime and would appreciate it if someone could point out to me what I'm doing incorrectly here.
Upvotes: 2
Views: 940
Reputation: 71350
The question How can I create my own data structure with an iterator that returns mutable references? does a good job explaining why it is disallowed. But despite what said, or at least implied there that it is impossible to do that without unsafe code ("Now you may wonder: How did the standard library authors manage to write the mutable vector iterator? The answer is simple: They used unsafe code."), for pure slices it is actually possible.
The trick is simple: instead of using self.slice
from the restrictive self
reference, replace it with an empty slice and now we have the slice with the full lifetime:
fn next(&mut self) -> Option<Self::Item> {
if self.slice.len() < 10 {
return None;
} else {
let slice = std::mem::take(&mut self.slice);
let (head, tail) = slice.split_at_mut(10);
self.slice = tail;
Some(MyStruct { slice: head })
}
}
Upvotes: 3