The mutable reference lifetime problem of iterators

I have a piece of code:

#[derive(Clone, Copy, Debug)]
struct Ab {
    a: u32,
    b: u32,
}

#[derive(Clone, Copy, Debug)]
struct MeAb {
    a: u32,
    b: [Ab; 5],
}

struct Iter<'a> {
    idx: u32,
    inner: &'a mut MeAb,
}

impl<'a> Iter<'a> {
    fn new(inner: &'a mut MeAb) -> Self {
        Self { idx: 0, inner }
    }
}

impl MeAb {
    fn iter(&mut self) -> Iter {
        Iter::new(self)
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a mut Ab;

    fn next(&mut self) -> Option<Self::Item> {
        if self.idx < 5 {
            let ret = &mut self.inner.b[self.idx as usize];
            self.idx += 1;
                return Some(ret)
        } else {
            return None
        }
    }
}

fn main() {
    let mut cc = MeAb {
        a: 0,
        b: [Ab { a: 1, b: 2 }; 5]
    };

    for i in cc.iter() {
        i.a = 5;
        println!("i {:?}", i);
    }
    println!("cc {:?}", cc);
}

Now, There are the following errors:

error: lifetime may not live long enough
  --> kernel/init/src/main.rs:37:24
   |
30 | impl<'a> Iterator for Iter<'a> {
   |      -- lifetime `'a` defined here
...
33 |     fn next(&mut self) -> Option<Self::Item> {
   |             - let's call the lifetime of this reference `'1`
...
37 |                 return Some(ret)
   |                        ^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

error: could not compile `init` due to previous error

What should I do to return a mutable reference in an iterator?

The technical problem is that in the iterator if you create a mutable reference you'll get one with the lifetime of the &mut self parameter, which is less than the 'a lifetime. To visualize this you can imagine that the 'a lifetime is "bigger" than the iterator itself (i.e. while the iterator is valid, so is 'a), but the lifetime of &mut self is valid only for the call to next. There isn't a clear way to solve this because this is the symptom, not the real problem itself.

The fundamental problem is that your Iterator still contains a reference to the same data you yielded a reference to, thus crating two mutable references to the same data, which is not valid in Rust. Thus you need a way to guarantee to the compiler you won't keep such mutable reference in the iterator. The simpliest way would be to wrap a std::slice::IterMut, which is the standard iterator over slices, the one you get when calling .iter_mut().

#[derive(Clone, Copy, Debug)]
struct Ab {
    a: u32,
    b: u32,
}

#[derive(Clone, Copy, Debug)]
struct MeAb {
    a: u32,
    b: [Ab; 5],
}

struct Iter<'a> {
    inner: std::slice::IterMut<'a, Ab>,
}

impl<'a> Iter<'a> {
    fn new(inner: &'a mut MeAb) -> Self {
        Self { inner: inner.b.iter_mut() }
    }
}

impl MeAb {
    fn iter(&mut self) -> Iter {
        Iter::new(self)
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a mut Ab;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}

fn main() {
    let mut cc = MeAb {
        a: 0,
        b: [Ab { a: 1, b: 2 }; 5]
    };

    for i in cc.iter() {
        i.a = 5;
        println!("i {:?}", i);
    }
    println!("cc {:?}", cc);
}

Thank you very much. It solved my problem and clearly let me know what was wrong.

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.