Help Understanding Lifetime Restrictions?

I've been trying to understand this post on Stack Overflow along with its accepted answer. The context is the well-known example of trying to use safe code to write IterMut for a data structure wrapping a slice stored on the heap.

First of all, it's obvious why one can't have two mutable references to the same slice at the same time. However, the answer on this post says that, given the fact that the lifetime of the return value of next() must be the same as the lifetime of the iterator, two calls would cause a violation. I'm confused by that in and of itself - there are lots of functions that I could write that would yield a mutable reference to some internal state, and the borrow checker wouldn't complain until I tried to hold onto two of them at the same time. So the first part of my question is what makes this a special case that cares about some particular possible usage.

That said, the actual compiler error obviously doesn't say anything about potential multiple calls to next() - it talks about conflicting lifetimes, which makes more sense to me. What I don't understand is what the two conflicting lifetimes are. The compiler is saying it can't find a lifetime that satisfies both 'a from the iterator as well as the autoref in the get_mut() function. The second part of my question is: why can't the compiler take the anonymous lifetime to be 'a?

The problem is that your examples of returning mutable references to internal state have different lifetimes than the Iterator::next method does. The lifetimes on Iterator::next are:

impl<'a> MyType<'a> {
    fn next<'b>(&'b mut self) -> &'a mut InternalState { ... }

But the default lifetimes you get on a method that returns a mutable reference to internal state are:

impl<'a> MyType<'a> {
    fn next<'b>(&'b mut self) -> &'b mut InternalState { ... }

If the lifetime isn't tied to the borrow of self, then the compiler wont prevent you from calling it multiple times while keeping previous values around.

That makes sense, but I would have thought that in the linked example I'd end up with a function that I was only allowed to call once because the lifetime is tied to the iterator. Why is it a compile error instead?

The Iterator trait requires the next method to have a certain signature, and if it doesn't have that signature, you get a compilation error.

I see it now - I had been imagining a scenario wherein this would work as long as 'b was smaller than 'a, but of course the signature is telling us that it has to work for all 'b and 'a. And furthermore, as you implied above, we need this particular signature in order to get a useful iterator instead of the useless one that you can only call once.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.