How to mutably borrow elements in a Vec

As usual, I know the problem but cant find a way out. :frowning:

Problem definition:
My function take a &'b mut Vec<Detail<T>> and returns a Option<Vec<&'a mut Detail<T>>>. The returned &mut refer to elements within borrowed &mut Vec.

struct Detail<T> {
    value: T,
    required_by: Option<Vec<usize>>,
    compute_function: Option<Box<dyn Fn(&[T]) -> T>>,
}

impl Detail<T> {

    fn get_detail_reqs<'a, 'b: 'a>(&self, store: &'b mut Vec<Detail<T>>) -> Option<Vec<&'a mut Detail<T>>> {
        if let Some(v) = self.required_by.borrow() {
            let mut r = Vec::with_capacity(v.len());
            for index in v.iter() {
                let d = store.get_mut(*index).unwrap();
                r.push(d);
            }
            Some(r)
        } else {
            None
        }
    }
}

That gives me

error[E0499]: cannot borrow `*store` as mutable more than once at a time
  --> src/lib.rs:77:25
   |
71 |     fn get_detail_reqs<'a, 'b: 'a>(&self, store: &'b mut Vec<Detail<T>>) -> Option<Vec<&'a mut Detail<T>>> {
   |                        -- lifetime `'a` defined here
...
77 |                 let d = store.get_mut(*index).unwrap();
   |                         ^^^^^^^^^^^^^^^^^^^^^ `*store` was mutably borrowed here in the previous iteration of the loop
...
80 |             Some(r)
   |             ------- returning this value requires that `*store` is borrowed for `'a`

How to make this work?
Im also thinking &vec would outlive elements inside the vec. Is this right?

UPDATE:
This also works:
fn get_detail_reqs<'a>(&self, store: &'a mut Vec<Detail<T>>) -> Option<Vec<&'a mut Detail<T>>> but is it right? My vec def will outlive elements within.

mut is not merely mutable, but exclusive and invariant (maximally inflexible). When you call store.get_mut(index) it borrows all of store exclusively. It has no way of knowing that indices don't overlap, and because it promises absolute exclusivity, it can only permit borrowing one item at a time.

If you know every index is unique, then you will have to use unsafe here to override the lifetimes.

By using get_mut multiple times, the compiler can't prove that you don't access the same item twice. Indeed, it could be possible for your program to attempt this. You can create multiple shared references, which would be Vec<&'a mut Detail<T>>, the only restriction being you can't mutate any of the contents. Alternatively, you could clone the contents.

No, a reference to a Vec<T> (&Vec<T>) is always outlived by its contents, unless the reference is mutable and you remove the elements.

Here's one (safe) way where the Vec<&mut Detail> is turned into a HashMap<usize, &mut Detail>, and this map is used to ensure that every mutable reference is collected at most once. The version I gave ignores duplicate and too-large indices. The version in comments would panic on them instead.

If the indices are always sorted or reverse sorted, there are some other pretty straight-forward safe ways to solve it.

1 Like

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.