2

The following code doesn't compile:

struct Things {
    things: Vec<usize>
}

struct ThingsIterMut<'a> {
    contents: &'a mut Vec<usize>,
    indices: std::slice::Iter<'a, usize>
}

impl<'a> Iterator for ThingsIterMut<'a> {
    type Item = &'a mut usize;

    fn next(&mut self) -> Option<Self::Item> {
        match self.indices.next() {
            None => None,
            Some(i) => self.contents.get_mut(*i)
        }
    }

}

impl Things {
    pub fn iter_mut<'a>(&'a mut self) -> ThingsIterMut<'a> {
        ThingsIterMut {
            contents: &mut self.things,
            indices: self.things.iter()
        }

    }
}

fn main() {
    println!("Hello, world!");
}

It complains:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:16:24
   |
16 |             Some(i) => self.contents.get_mut(*i)
   |                        ^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 13:5...
  --> src/main.rs:13:5
   |
13 |     fn next(&mut self) -> Option<Self::Item> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:16:24
   |
16 |             Some(i) => self.contents.get_mut(*i)
   |                        ^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 10:6...
  --> src/main.rs:10:6
   |
10 | impl<'a> Iterator for ThingsIterMut<'a> {
   |      ^^
note: ...so that the types are compatible
  --> src/main.rs:13:46
   |
13 |       fn next(&mut self) -> Option<Self::Item> {
   |  ______________________________________________^
14 | |         match self.indices.next() {
15 | |             None => None,
16 | |             Some(i) => self.contents.get_mut(*i)
17 | |         }
18 | |     }
   | |_____^
   = note: expected `std::iter::Iterator`
              found `std::iter::Iterator`

Changing next to next(&'a mut self) dose not work (signature mismatch), neither does change self.contents.get_mut() to self.contents.get_mut::<'a>().

What's the correct way to address this issue?

Jmb
  • 18,893
  • 2
  • 28
  • 55
Incömplete
  • 853
  • 8
  • 20
  • 2
    This seems to be a case where you need a "[streaming iterator](http://lukaskalbertodt.github.io/2018/08/03/solving-the-generalized-streaming-iterator-problem-without-gats.html)". In short, the `Iterator` trait makes it valid to retain multiple values produced by the iterator, as in `let a = it.next(); let b = it.next();`. With your implementation that would create two mutable references into the `contents` vector, which is not allowed. – user4815162342 Feb 23 '21 at 08:34
  • 1
    Does this answer your question? [How can I create my own data structure with an iterator that returns mutable references?](https://stackoverflow.com/questions/25730586/how-can-i-create-my-own-data-structure-with-an-iterator-that-returns-mutable-ref) Or perhaps [How to implement Iterator yielding mutable references?](https://stackoverflow.com/q/60072498) – kmdreko Feb 23 '21 at 13:40

1 Answers1

0

I see two problems. The first is that your iter_mut function tries to return both a mutable and an immutable reference to self.things.

It is easier to see why the borrow checker doesn't allow this by simplifying it:

fn main() {
    let mut things = vec![1, 2, 3];
    let contents = &mut things;
    let indices = things.iter(); // borrows self_things immutably
    let things_iter_mut = (contents, indices);
}

The second problem that you are trying to return a longer reference than you pass into the next function.

struct Things<'things> {
    contents: &'things mut Vec<usize>,
}

impl<'things> Things<'things> {
    // This won't compile! The 'borrow lifetime is implied.
    // But here you can see that the borrow might be shorter than
    // what we are returning.
    fn next(&'borrow mut self) -> &'things mut Vec<usize> {
        self.contents
    }

    // This will compile. Because the returned reference lives
    // just as long as the argument.
    fn next(&'things mut self) -> &'things mut Vec<usize> {
        self.contents
    }
}
Hadus
  • 1,551
  • 11
  • 22