2

I'm creating a custom data structure in Rust and trying to implement iterators for it. Following the example of the built-in collections (LinkedList, Vec, etc), I've created an IntoIter struct that iterates over an owned collection, an Iter struct that iterates over a borrowed collection, and an IterMut struct that iterates over a mutably borrowed collection.

I was able to implement the first two iterators but I'm having trouble pleasing the borrow-checker with IterMut. I've cut my code down to the bare minimum repro and replaced my custom data structure with Vec<Option<T>>:

pub struct IterMut<'a, T: 'a> {
    list: &'a mut Vec<Option<T>>,
}

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        let head_node = &mut self.list[0];
        // convert &mut Option<T> to Option<&mut T>
        head_node.as_mut()
    }
}

The example in the playground

It fails to compile with

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:23:24
   |
23 |   let head_node = &mut self.list[0];
   |                        ^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:2...
  --> src/main.rs:22:2
   |
22 | /  fn next(&mut self) -> Option<&'a mut T> {
23 | |   let head_node = &mut self.list[0];
24 | |   // convert &mut Option<T> to Option<&mut T>
25 | |   head_node.as_mut()
26 | |  }
   | |__^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:23:24
   |
23 |   let head_node = &mut self.list[0];
   |                        ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 19:1...
  --> src/main.rs:19:1
   |
19 | / impl<'a, T> Iterator for IterMut<'a, T> {
20 | |  type Item = &'a mut T;
21 | |
22 | |  fn next(&mut self) -> Option<&'a mut T> {
...  |
26 | |  }
27 | | }
   | |_^
note: ...so that expression is assignable (expected std::option::Option<&'a mut T>, found std::option::Option<&mut T>)
  --> src/main.rs:25:3
   |
25 |   head_node.as_mut()
   |   ^^^^^^^^^^^^^^^^^^

What really confuses me about this is that this code is almost identical to the code I used for Iter, which compiles successfully:

pub struct Iter<'a, T: 'a> {
    list: &'a Vec<Option<T>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        let head_node = &self.list[0];
        // convert &Option<T> to Option<&T>
        head_node.as_ref()
    }
}

I know that & and &mut are two different things, but I thought their lifetimes would still be calculated the same way. My first guess was that as_ref() must be somehow different than as_mut() but there doesn't appear to be a difference in the source code of their implementations (as_ref, as_mut).

What is the borrow-checker complaining about?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Brian
  • 149
  • 1
  • 7
  • Your reduced example shows the problem quite nicely. By returning the same mutable reference multiple times (`&mut self.list[0]`) you would be breaking Rust's rules for references! [Here's the duplicate answer applied to your code](https://play.rust-lang.org/?gist=2d88bfe774873d73543e9a0f1b4ede2d&version=stable). – Shepmaster Dec 18 '17 at 01:55

0 Answers0