(rust book chapt. "unsafe rust") is my explanation right as to why this wont compile?

Hello,
This will not compile because there are two borrows on the same variable "values". If I would change the
return type to "(mut[i32], mut[i32])" it would mean that the owner would go out of scope at the end of the function so the values would be dropped there right?

fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = values.len();

    assert!(mid <= len);

    (&mut values[..mid], &mut values[mid..])
}
  1. mut [i32] isn't a type. You might be confusing &mut _ references with let mut x = ... bindings. The latter is basically a built-in lint. mut bindings don't change the type of the variable, they just allow you to overwrite it and take a &mut _ to it. In contrast &T and &mut T are two significantly different types.

  2. [i32] has a dynamic length (and thus size). We also say it is not Sized, or that it is unsized. You can't pass unsized types by value, so you can't return such a thing.

  3. The function doesn't own the slice ([i32]) or the values in it, since it takes them by reference.

So...

  • You can't return (mut [i32], mut [i32]) because those aren't types
  • You can't return ([i32], [i32]) because those are unsized types
  • You can't make *values go out of scope

If the compiler understood non-overlapping ranged-index operations on slices, the function could soundly compile -- the two slices don't alias each other. But it doesn't, which is why the actual split_at_mut is ultimately implemented via raw pointer operations.

1 Like

thanks again for your explanation! :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.