Iter of mut item of selected index: cannot infer an appropriate lifetime

Given:

pub struct Children<'a> {
    tape: &'a mut [Slot],
    cursors: Vec<usize>, // some non-overlapping indexes within tape
}

pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Slot> {

        // Failed:
        // self.cursors.iter().filter_map(|c| self.tape.get_mut(*c))

        // Ok:
        self.tape
            .iter_mut()
            .enumerate()
            .filter(|(i, _)| self.cursors.contains(&i))
            .map(|(_, s)| s)
}

Any idea to not loop all item in self.tape?

1 Like

If your indexes are sorted, then you could probably get it to with a split_at_mut thing, but otherwise you can only do it with unsafe or by looping through everything with iter_mut.

1 Like

unsafe version, should be ok if make sure self.cursors is non-overlapping ?

self.cursors.iter().map(|c| unsafe {
let ptr = self.tape.get_unchecked_mut(*c) as *mut Slot;
&mut *ptr
})

Well, it's a bit complicated because the full slice will overlap with the previously returned mutable references, so touching the full slice again invalidates those previous references. It's better to use a raw pointer like this:

pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Slot> {
    let ptr = self.tape.as_mut_ptr();
    self.cursors.iter().map(move |c| unsafe {
        let elem_ptr = ptr.add(*c);
        &mut *elem_ptr
    })
}

Obviously, the above code is only correct if you know up-front that all indexes are in-bounds and that they are all distinct.

2 Likes

Safe version, assuming cursors is sorted:

pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Slot> {
    let mut next_idx = 0;
    let mut tape = self.tape.iter_mut();
    self.cursors
        .iter()
        .filter_map(move |&idx| {
            let value = tape.nth(idx - next_idx);
            next_idx = idx + 1;
            value
        })
}
5 Likes

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.