Cannot infer an appropriate lifetime for

It's my code:

struct R<'a> {
    r: &'a mut [i32]
}

impl<'a> R<'a> {
    fn iter_mut(&'a mut self) -> IterMut<'a> {
        IterMut { collection: self.r, current: 0 }
    }
}

struct IterMut<'a> {
    collection: &'a mut [i32],
    current: usize
}

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

    fn next(&mut self) -> Option<Self::Item> {
        if self.current < self.collection.len() {
            self.current += 1;
            Some(&mut self.collection[self.current - 1])
        } else {
            None
        }
    }
}

fn main() {
    let mut v = [1,2,3,4,5];
    let rrr = R { r: &mut v };

    for e in rrr.iter_mut() {
        print!("{} ", e);
    }
}

And compiler gives an error: (I can not understand what is wrong and how to fix it)


Thanks!

The issue is that your iterator returns a mutable reference to the slice it contains without borrowing the iterator. Thus you now have two overlapping mutable references, neither of which is a borrow of the other. This is not allowed in Rust. To fix this, replace the slice with a shorter slice to avoid the overlap like this:

struct IterMut<'a> {
    collection: &'a mut [i32],
}

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

    fn next(&mut self) -> Option<Self::Item> {
        // take replaces self.collection with an empty slice
        let slice = std::mem::take(&mut self.collection);
        match slice.split_first_mut() {
            Some((head, tail)) => {
                self.collection = tail;
                Some(head)
            }
            None => None
        }
    }
}

playground

Alternatively you can reuse the IterMut already found in the standard library like this.

The reason that the returned reference is not considered a borrow of the iterator is that the signature of next looks like this with elided lifetimes inserted:

fn next<'s>(&'s mut self) -> Option<&'a mut i32>

Notice how the reference doesn't use the lifetime parameter of the self argument. The fact that the lifetimes do not match means that the return value is not a borrow of the iterator. (Instead, it's considered a borrow of the R you created the iterator from.)

This allows you to call next multiple times without throwing the previous item away.

// this is ok
let mut iter = rrr.iter_mut();

let a = iter.next().unwrap();
let b = iter.next().unwrap();

println!("{}", *a);
println!("{}", *b);

playground

3 Likes

Thank you!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.