スライスへの可変借用の分割には専用のメソッドが必要になる。

背景

スライスの各要素は構造体の各フィールドと異なり、そのままでは別々に排他参照を得る事ができない。これは要素のインデックスが動的になるパターンにおいて、重複を検出する手段がないためである。

構造体の場合


fn main() {
    let mut obj = MyStruct {a: 0, b: 0};
    let a = &mut obj.a;
    let b = &mut obj.b;
    *a += 1;
    *b += 1;
    assert_eq!(obj.a, obj.b);
}

struct MyStruct {
    a: i32,
    b: i32,
}

スライスの場合


fn main() {
    let mut obj = [0, 0];
    let a = &mut obj[0];
    let b = &mut obj[1];
    *a += 1;
    *b += 1;
    assert_eq!(obj[0], obj[1]);
}

error[E0499]: cannot borrow `obj[_]` as mutable more than once at a time
 --> src\main.rs:4:13
  |
3 |     let a = &mut obj[0];
  |             ----------- first mutable borrow occurs here
4 |     let b = &mut obj[1];
  |             ^^^^^^^^^^^ second mutable borrow occurs here
5 |     *a += 1;
  |     ------- first borrow later used here
  |
  = help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices

メソッド

スライスを重複なく分割できれば、複数の排他参照を提供できる。

以下はそうした分割を保証したメソッドの抜粋である。

slice::split_at_mut
位置指定して分割 (範囲外はパニック)
slice::split_at_mut_checked
位置指定して分割 (範囲外は結果なし)
slice::split_at_mut_unchecked
位置指定して分割 (範囲外は未定義) 
slice::split_first_mut
先頭とその他に分割
slice::split_last_mut
末尾とその他に分割
slice::iter_mut
イテレータでの分割 (要素ごと)
slice::split_mut
イテレータでの分割 (グループごと)
slice::get_disjoint_mut
インデックスの配列から各参照を取得
str::split_at_mut
位置指定して分割 (範囲外はパニック)
str::split_at_mut_checked
位置指定して分割 (範囲外は結果なし)

サンプル


fn main() {
    let mut obj = [0, 0];
    let (a, b) = obj.split_at_mut(1);
    a[0] += 1;
    b[0] += 1;
    assert_eq!(obj[0], obj[1]);
}