How can I get multiple disjoint mutable references to a vector while retaining the ability to create immutable references?

#1

Hello,
I have a vector of usize's (Vec<usize>), and I need to get multiple disjoint mutable slices (&mut [usize]), and still be able to get an arbitrary number of immutable slices (&[usize]) to the same vector. Any ideas? The vector’s size will not change, and the “snip locations” (the addresses at which the mutable references start and end) remain the same. I could just use Vec<RefCell<Vec>> (the Vec contained by the RefCell contains the contents that the disjoint mutable slices should contain), but RefCell isn’t thread safe. Is there an efficient, threadsafe way to do this?

1 Like
#2

The v.split_at_mut(i) method on slices (and thus Vecs) will magically give you (&mut v[.. i], &mut v[i ..]) without the compiler complaining. You can then keep splitting on any of those elements to get as many “independent” (non overlapping) mutable views on the vector as you need.

Finally, you can then use &mut [_] where &[_] is required, since a unique reference (i.e., &mut) can always be seen as a potentially non unique one (i.e., &).

3 Likes
#3

Thanks! What’s the overhead of split_at_mut?

1 Like
#4

Zero. It compiles to pointer arithmetic.

3 Likes
#5

There’s also the bounds check…

#6

True, but if you know the maximum splitting index you will be using (let’s call it n), then you can prefix the code with an assert!(n <= v.len(), "Index out of bounds"); and LLVM should then be smart enough to optimize away all the following bound checks.

#OneBoundCheckToRuleThemAllAndInTheOptimizerBindThem

5 Likes
#7

Oh wow, that’s pretty neat!

#8

A quick demonstration of this: https://rust.godbolt.org/z/VEBior

1 Like