Cannot borrow as mutable variable created with "let mut"

I'm trying to write a test and running into a problem. Here's the code:

  fn test_mix3parts_1(plain:&[u8],cipher:&[u8]) {
    let mut text_copy=plain.clone();
    let len=plain.len();
    let third=len/3;
    let rprime=find_max_order(third as u64) as usize;
    mix3parts(&mut text_copy,len,rprime);
    assert_eq!(text_copy,cipher);
    mix3parts(&mut text_copy,len,rprime);
    assert_eq!(text_copy,plain);
  }

  #[test]
  fn test_mix3parts() {
    test_mix3parts_1(&[0x00,0x0d,0x1a,0x27,0x34,0x41,0x4e,0x5b,0x68,0x75,0x82,0x8f,0x9c,0xa9,0xb6,0xc3],
                     &[0xd9,0x74,0xd1,0xbc,0x29,0x5a,0x42,0x2b,0x51,0x87,0xa0,0xcd,0x0a,0x16,0x41,0xc3]);
  }

It's in mix3.rs in GitHub - phma/Kaftor.jl: Keyed affine transform · GitHub, and I got the test vector by running the corresponding Julia code. When I try to compile it, I get

error[E0596]: cannot borrow data in a `&` reference as mutable
   --> src/mix3.rs:161:15
    |
161 |     mix3parts(&mut text_copy,len,rprime);
    |               ^^^^^^^^^^^^^^ cannot borrow as mutable

error[E0596]: cannot borrow data in a `&` reference as mutable
   --> src/mix3.rs:163:15
    |
163 |     mix3parts(&mut text_copy,len,rprime);
    |               ^^^^^^^^^^^^^^ cannot borrow as mutable

along with warnings about unused code because I haven't finished writing it. text_copy was created with let mut, so why can't it be borrowed as mutable?

text_copy is of type &[u8], i.e. an immutable reference to a slice of bytes.
That text_copy itself is mutable does not matter for your use case, since it does not own the data of the slice behind the reference.
I.e. the mut in this case just lets you reassign the value of text_copy (which is irrelevant to your use case).
In order to be able to modify the bytes behind the reference to the slice, the reference itself must be mutable:

fn test_mix3parts_1(plain: &mut [u8], cipher: &[u8]) {
    ...
}

In this case, the call to .clone() is also unnecessary, since you can just reborrow the mutable reference.

[u8] don't implement Clone -- they cannot, they're not Sized -- so instead you end up cloning the &[u8] into another &[u8].

You probably meant plain.to_owned() to get a Vec<u8> instead of plain.clone().

mix3parts has signature:

pub fn mix3parts(buf: &mut[u8], len: usize, rprime: usize) { ... }

Which means that buf must be a mutable slice.

But when you write

fn test_mix3parts_1(plain:&[u8],cipher:&[u8]) {
    let mut text_copy=plain.clone();
    ...
}

The type of test_copy is still &[u8] (immutable slice of bytes). What is mutable is the binding (text_copy name). So you could overwrite it. But it's never possible to write to memory pointed at by shared reference. In C terms you created const u8*, but you want to use it as u8* const.

It is hard to give you general solution for this, as I'm not sure how your testing approach is structured. But one thing you can work is to crate an owned copy (ie. Vec<u8>), which you can later borrow as mutable slice.

fn test_mix3parts_1(plain:&[u8],cipher:&[u8]) {
    let mut text_copy = plain.to_owned();
    // ...
    mix3parts(&mut text_copy,len,rprime);
``

to_owned works. Committed and pushed.