Implement iter_mut on custom type

I've gotten stuck with trying to implement iter_mut() on my custom type and haven't been able to find answers online. I've got it working in a similar way with immutable iter() which doesn't seem to work with making it mutable.

struct ChannelConfig{
    data: u32,
    channel: Channel,
    etc...
}

struct Channels {
    pub a: ChannelConfig,
    pub b: ChannelConfig,
    pub c: ChannelConfig,
    pub d: ChannelConfig,
}

struct MyIterMut<'a> {
    channels: &'a mut Channels,
    next_chan: Option<Channel>,
}

impl<'a> Iterator for MyIterMut<'a> {
    type Item = &'a mut ChannelConfig;

    fn next(&mut self) -> Option<Self::Item> {
        match self.next_chan {
            Some(Channel::A) => {
                self.next_chan = Some(Channel::B);
                let chan_config = &mut self.channels.a;
                Some(chan_config)
            }
            Some(Channel::B) => {
                self.next_chan = Some(Channel::C);
                let chan_config = &mut self.channels.b;
                Some(chan_config)
            }
            Some(Channel::C) => {
                self.next_chan = Some(Channel::D);
                let chan_config = &mut self.channels.c;
                Some(chan_config)
            }
            Some(Channel::D) => {
                self.next_chan = None;
                let chan_config = &mut self.channels.d;
                Some(chan_config)   //<----- Lifetime may not live long enough
            }
            None => None,
        }
    }
}

I've made an iterator struct (MyIterMut) to hold a mutable reference to the struct I'm wanting to iterate over and labelled the lifetime of my Channels struct but I still get the lifetime error and can't solve it:

error: lifetime may not live long enough
   --> src\foo.rs:104:17
    |
81 | impl<'a> Iterator for MyIterMut<'a> {
    |      -- lifetime `'a` defined here
...
84 |     fn next(&mut self) -> Option<Self::Item> {
    |             - let's call the lifetime of this reference `'1`
...
104 |                 Some(chan_config)
    |                 ^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

I think I understand that it's saying I'm returning a reference with the lifetime of the MyIterMut struct and not the ChannelConfig struct itself. How do I properly specify this lifetime or return it properly such that it has the correct lifetime?

Thanks!

The compiler doesn't know that your enum is attempting to prevent two different items in Channels from being accessed simultaneously, so I don't know if there's a way to express that promise safely.

But what you can do is simply collect your exclusive references into something iterable instead, like:

impl Channels {
    fn iter_mut(&mut self) -> impl Iterator<Item = &mut ChannelConfig> {
        [&mut self.a, &mut self.b, &mut self.c, &mut self.d].into_iter()
    }
}

Or maybe pop them off a VecDeque newtype if your iterator needs some additional functionality.

3 Likes

To explain the borrow check error, in next, you have a

self: &'this mut MyIterMut<'a> {
    channels: &'a mut Channels,
    ...
}

So you have a nested &'short mut &'long mut Channels in a sense. You can't reborrow something from the inner &'long mut for 'long, only for 'short. Otherwise you would be able to have two active &mut to the same memory, which is UB.

This isn't a problem with shared references, because they are Copy -- you can copy the &'long _ from within a &'short &'long _.

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.