Why does IterMut have the wrong lifetimes?
⚓ Rust 📅 2026-01-23 👤 surdeus 👁️ 1I have a simple and straightforward implementation of an iterator over a slice:
struct Iter<'a, T> {
slice: &'a [T],
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
let (first, rest) = self.slice.split_first()?;
self.slice = rest;
Some(first)
}
}
The Iter struct contains a reference to a slice of T and iterates by splitting off the first element of the slice via <[T]>::split_first, setting self.slice to the remaining elements, and returning the reference to the first element inside Some. Very straightforward and understandable. Compiles fine and functions correctly.
But when I go to implement an iterator over mutable references to the elements of a slice using the same pattern, I get a lifetime error:
struct IterMut<'a, T> {
slice: &'a mut [T],
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next<'next>(&'next mut self) -> Option<Self::Item> {
let (first, rest) = self.slice.split_first_mut()?;
self.slice = rest;
Some(first) // Error: Lifetime may not live long enough
}
}
The borrow checker complains that the Iterator::next method was supposed to return data with lifetime 'a but it is returning data with lifetime 'next.
Can someone provide an in-depth explanation of exactly what is going on here? Why does the return value of IterMut::next have lifetime 'next and not 'a? Why does IterMut::next have this problem but Iter::next does not? What exactly is different about &mut T compared to &T that causes this lifetime error in the &mut T case?
I also understand that the lifetime error in the IterMut case can be solved by taking the value out of self.slice with std::mem::take and then splitting that to get the reference to the first element like so:
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next<'next>(&'next mut self) -> Option<Self::Item> {
- let (first, rest) = self.slice.split_first_mut()?;
+ let slice = std::mem::take(&mut self.slice);
+ let (first, rest) = slice.split_first_mut()?;
self.slice = rest;
Some(first) // Error: Lifetime may not live long enough
}
}
Why does this work? Can you explain this fix and how it is different from the failing implementation above?
6 posts - 4 participants
🏷️ Rust_feed