Overcoming `cannot borrow as mutable more than once at a time` for an array

Greetings!

I need to borrow array mutable more that once and I can't get how can I do this.
I have the following code:

    // Self([u32; 5])
    pub fn rotr(&mut self) {
        let arr = &mut self.0;
        let (a0, a1, a2, a3, a4) = (
            &mut arr[0],
            &mut arr[1],
            &mut arr[2],
            &mut arr[3],
            &mut arr[4],
        );
        let (b0, b1, b2, b3, b4) = (*a0 & 0b1, *a1 & 0b1, *a2 & 0b1, *a3 & 0b1, *a4 & 0b1);

        *a0 >>= 1;
        *a1 >>= 1;
        *a2 >>= 1;
        *a3 >>= 1;
        *a4 >>= 1;

        *a0 |= b4 << 31;
        *a1 |= b0 << 31;
        *a2 |= b1 << 31;
        *a3 |= b2 << 31;
        *a4 |= b3 << 31;
    }

I want to borrow multiple times to get rid of extra borrow-cheking. I can use get_unchecked_mut, but code become unreadable.

The borrow checker needs a guarantee that loans don't overlap, but it's not capable of tracking which indexes are borrowed.

You can overcome that with either split_at_mut or in this case, mutable iterators:

let mut items = self.0.iter_mut();
let a1 = items.next().unwrap();
let a2 = items.next().unwrap();
let a3 = items.next().unwrap();

The unwrap() will be optimized away.

Since the length is known at compile-time, you can use pattern matching:

let [a0, a1, a2, a3, a4] = &mut self.0;

This gives you references into self.0 due to the match ergonomics feature, where pattern matching on a reference to something is like matching on the thing itself, except that the fields become references of the same type.

4 Likes

Ah, yes, I totally forgot about that =)
Thanks!