Conflicting lifetime requirements in mutable Iterator


#1

Hi,

I am writing a special kind of container for which I would like to provide an Iterator. The immutable Iterator does not pose a problem but the mutable one. This is a minimal example:

trait Item {}

impl Item for u32 {}

struct Container<T: Item> {
    data: Vec<T>,
}

struct IterMut<'a, T: 'a + Item> {
    container: &'a mut Container<T>,
    index: usize,
}

impl<'a, T: Item> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
        let item = &mut self.container.data[self.index]; // error here!
        Some(item)
    }
}

fn main() {
    let mut container = Container {
        data: vec![1u32, 2, 3],
    };
    let iter_mut = IterMut {
        container: &mut container,
        index: 0,
    };
    for i in iter_mut {
        // ...
    }
}

The resulting error is:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:17:25
   |
17 |         let item = &mut self.container.data[self.index]; // error here!
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 16:5...
  --> src/main.rs:16:5
   |
16 | /     fn next(&mut self) -> Option<Self::Item> {
17 | |         let item = &mut self.container.data[self.index]; // error here!
18 | |         Some(item)
19 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:17:25
   |
17 |         let item = &mut self.container.data[self.index]; // error here!
   |                         ^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 14:1...
  --> src/main.rs:14:1
   |
14 | impl<'a, T: Item> Iterator for IterMut<'a, T> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...so that the types are compatible:
           expected std::iter::Iterator
              found std::iter::Iterator

My guess is that a second shorter lifetime is required for the returned reference but I cannot figure out how to express that with 'x: 'y. Am I wrong?

Can somebody please explain what the problem is and how to fix the code?

Note: I could simply return the standard iterator of the Vec but this is not the point here.

Thanks


#2

In short, you’d need unsafe code in your example.