3

I want to uptade a slice through a mutable reference.

While this does work with immutable slices:

fn shrink(value: &mut &[u8]) {
    *value = &value[0..2];
}

fn main() {
    let a = [0; 4];
    let mut a_slice: &[u8] = &a;
    shrink(&mut a_slice);
    println!("{:?}", a_slice);
}

It doesn't work with mutable ones:

fn shrink<'a: 'b, 'b>(value: &'a mut &'b mut [u8]) {
    *value = &mut value[0..2];
}

fn main() {
    let mut a = [0; 4];
    let mut a_slice: &mut [u8] = &mut a;
    shrink(&mut a_slice);
    println!("{:?}", a_slice);
}

Error message:

error[E0502]: cannot borrow `a_slice` as immutable because it is also borrowed as mutable
 --> src/main.rs:8:22
  |
7 |     shrink(&mut a_slice);
  |            ------------ mutable borrow occurs here
8 |     println!("{:?}", a_slice);
  |                      ^^^^^^^
  |                      |
  |                      immutable borrow occurs here
  |                      mutable borrow later used here

I know that there is a way to update the slice by directly returning a subslice.

But is there a way to make rereferencing a mutable slice through mutable reference possible?

The problem is similar to this one, but I can't figure what makes it so different, that proposed solution doesn't work.

Stargateur
  • 24,473
  • 8
  • 65
  • 91
huh-hulk
  • 185
  • 10
  • 2
    The duplicate [applied to your situation](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=acd8c6ed2a274aef138f6289f1ce3e8d). – trent Nov 24 '20 at 12:35
  • (If the indexing panics, and you recover from the panic with `catch_unwind`, `value` will now point to an empty slice. This might be undesirable, but I don't see a way around it, at least not in safe code.) – trent Nov 24 '20 at 12:43
  • Thank you for clearing things up again @trentcl : ) Your suggestion is exactly what I need. – huh-hulk Nov 24 '20 at 13:37

1 Answers1

2

I don't know what the problem is with that code, but one option would be to return the updated slice directly:

fn shrink(value: &mut [u8]) -> &mut [u8] {
    &mut value[0..2]
}

fn main() {
    let mut a = [0; 4];
    let mut a_slice = &mut a[..];
    a_slice = shrink(a_slice);
    println!("{:?}", a_slice);
}

Rather than updating via the mutable reference, updating in the caller makes it clear that the old value of a_slice won't be used any more.

Douglas
  • 36,802
  • 9
  • 76
  • 89
  • As I said, I know that it's possible to reassign the slice by returning the sub-slice, but It's not exactly what I need. Thank you for suggestion : ) – huh-hulk Nov 24 '20 at 13:48