3

Here is a minimal example for some behavior I stumbled on:

pub fn main() {
    let mut ibytes = "stump".as_bytes();
    let mut obytes: &mut[u8] = &mut [0u8; 1024];

    while ibytes.len() >= 2 {
        obytes[0] = ibytes[0] >> 2;
        obytes[1] = ibytes[0] & 0x03 << 4 | ibytes[1] >> 4;

        ibytes = &ibytes[2..];
        obytes = &mut obytes[2..];
    }
}

The following code doesn't compile, because the slice view operation on "obytes" do borrowing recursively, while the similar operation on "ibytes" is OK.

The error message is shown as bellow:

<anon>:6:9: 6:35 error: cannot assign to `obytes[..]` because it is borrowed
<anon>:6         obytes[0] = ibytes[0] >> 2;
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:10:23: 10:29 note: borrow of `obytes[..]` occurs here
<anon>:10         obytes = &mut obytes[2..];
                                ^~~~~~
<anon>:7:9: 7:59 error: cannot assign to `obytes[..]` because it is borrowed
<anon>:7         obytes[1] = ibytes[0] & 0x03 << 4 | ibytes[1] >> 4;
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:10:23: 10:29 note: borrow of `obytes[..]` occurs here
<anon>:10         obytes = &mut obytes[2..];
                                ^~~~~~
<anon>:10:9: 10:34 error: cannot assign to `obytes` because it is borrowed
<anon>:10         obytes = &mut obytes[2..];
                  ^~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:10:23: 10:29 note: borrow of `obytes` occurs here
<anon>:10         obytes = &mut obytes[2..];
                                ^~~~~~
<anon>:10:23: 10:29 error: cannot borrow `*obytes` as mutable more than once at a time
<anon>:10         obytes = &mut obytes[2..];
                                ^~~~~~
<anon>:10:23: 10:29 note: previous borrow of `*obytes` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `*obytes` until the borrow ends
<anon>:10         obytes = &mut obytes[2..];

How can I do recursive borrow for mutable "obytes" like what has done for immutable “ibytes"?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
user2288954
  • 65
  • 1
  • 7

1 Answers1

2

This is an annoyance of the current borrow checker. You can work around it by clearly transferring the mutable borrow using an temporary intermediate variable:

pub fn main() {
    let mut ibytes = "stump".as_bytes();
    let mut obytes: &mut[u8] = &mut [0u8; 1024];

    while ibytes.len() >= 2 {
        obytes[0] = ibytes[0] >> 2;
        obytes[1] = ibytes[0] & 0x03 << 4 | ibytes[1] >> 4;

        ibytes = &ibytes[2..];
        let tmp = obytes;
        obytes = &mut tmp[2..];
    }
}

I'm pretty sure there's a Rust issue for this, but some quick searching didn't find it right away.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366