北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

rustのsliceとlen()

こう書くと、

fn main() {
    let mut a = [1, 2, 3, 4, 5];
    let x = &mut a[3..a.len()];
    println!("{:?}", x);
}

こう怒られる。

error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
 --> src/main.rs:3:23
  |
3 |     let x = &mut a[3..a.len()];
  |                  -----^-------
  |                  |    |
  |                  |    immutable borrow occurs here
  |                  mutable borrow occurs here
  |                  mutable borrow later used here

こうなら良い。

fn main() {
    let mut a = [1, 2, 3, 4, 5];
    let n = a.len();
    let x = &mut a[3..n];
    println!("{:?}", x);
}

3..a.len() を評価してから a の可変参照を取るならなんの問題もないような気もするのだが、実際このコードは、

use std::ops::IndexMut;

fn main() {
    let mut a = [1, 2, 3, 4, 5];
    let x = a.index_mut(3..a.len());
    println!("{:?}", x);
}

と同値であり、 &mut aa.len()fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Self::Output の引数となる。第1引数で可変参照を渡そうとしているのに第2引数で不変参照を用いているので怒られる。

error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
 --> src/main.rs:5:28
  |
5 |     let x = a.index_mut(3..a.len());
  |             - ---------    ^ immutable borrow occurs here
  |             | |
  |             | mutable borrow later used by call
  |             mutable borrow occurs here

まあそもそも、このサンプルのように末尾まで取りたいのなら、以下のように書くのが正しい。

fn main() {
    let mut a = [1, 2, 3, 4, 5];
    let x = &mut a[3..];
    println!("{:?}", x);
}

a.len() - 1 まで取りたいのなら分けて書かないと駄目なのかな。