I have defined some simple iterator types Iter
and IterMut
for immutable and mutable views respectively. These types are effectively just containers around a slice and an usize
index.
The implementation of the immutable Iter
variant compiles fine without any issues; however, as soon as the mut
keyword is added to the borrows and output type, the compiler begins to complain about the lifetime possibly not living long enough. The exact error is the commonly seen error of:
error: lifetime may not live long enough --> <source>:13:7 | 6 | impl<'a, T: 'a> Iterator for IterMut<'a, T> { | -- lifetime `'a` defined here ... 9 | fn next(&mut self) -> Option<&'a mut T> { | - let's call the lifetime of this reference `'1` ... 13 | Some(&mut self.data[self.index]) // Error occurs here! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: aborting due to previous error
What is puzzling to me is that the code between Iter
and IterMut
varies only by the presence of mut
. The code that triggered the above error is:
pub struct IterMut<'a, T: 'a> {
data: &'a mut [T],
index: usize,
}
impl<'a, T: 'a> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<&'a mut T> {
self.index += 1;
if self.index < self.data.len() {
Some(&mut self.data[self.index]) // Error occurs here!
} else {
None
}
}
}
Whereas nearly identical code with only mut
removed compiles fine:
pub struct Iter<'a, T: 'a> {
data: &'a [T],
index: usize,
}
impl<'a, T: 'a> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
self.index += 1;
if self.index < self.data.len() {
Some(&self.data[self.index]) // this works
} else {
None
}
}
}
I understand that the diagnostic is suggesting adding a lifetime parameter to &self
(although this would violate the definition of Iterator
), but it's really not clear to me why this is needed only if mut
is present.
Why does the presence of mut
make the compiler think that a lifetime isn't satisfied? What would the appropriate fix for this be?