Mutable iterator lifetimes problem

Hello, I struggle to figure out the right solution of a problem with lifetimes :frowning:

This works.
Uncommenting impl EnumerableMut for Pair breaks the program.

How to specify lifetimes to make the code working?

pub trait EnumerableMut {
    type Element;
    fn len(&self) -> usize;
    // fn element_mut( &mut self, index : usize ) -> &mut Self::Element;
    fn element_mut<'slf, 'element>(&'slf mut self, index: usize) -> &'element mut Self::Element
    where
        'element: 'slf;
}

Here the uncommented element_mut allows the caller to choose 'element to be pretty much any lifetime bigger than 'slf, including 'static for example. For the commented impl to compile you need the opposite bound, that is to allow 'element any lifetime smaller than 'slf (which is equivalent to the commented one).

This will however conflict with the Iterator implementation because it requires the item type to not be bound to the lifetime of &mut self, which is however the case here.

You can't have both the Iterator implementation and the implementation of EnumerableMut for Pair because they're fundamentally conflicting. The former requires the output to not be bound to the input, while the latter requires the opposite.

3 Likes

Put simply, the problem is that a (&mut self, index: usize) -> &mut Self::Element-style indexing function will never allow access to multiple elements concurrently (through this function), whereas an Iterator of &mut Self::Elements will always require support for concurrent access of all iterator items. So you simply cannot implement an Iterator using a function like element_mut. You can implement, say, a for_each function, or (in principle) a so-called “lending iterator” (though as far as I’m aware, we don’t have any good existing crate for those yet, and language support is limited).

The only reason why your iterator implementation is succeeding is because you have used an incorrect (or at least highly confusing) type signature for the element_mut method; as @SkiFire13 already hinted at,

fn element_mut<'slf, 'element>(&'slf mut self, index: usize) -> &'element mut Self::Element
where
    'element: 'slf;

is essentially the same as

fn element_mut(&mut self, index: usize) -> &'static mut Self::Element

(except that the former doesn’t require Element: 'static)

4 Likes

I see. Thank you for explanation :purple_heart: