Code Fix

中級

E0502: cannot borrow as mutable because it is also borrowed as immutable

不変参照が生きている(後で使われる)間に、同じ変数を可変で借用しようとするとE0502エラーになります。Rustの借用規則は「不変参照は何個でも、可変参照は同時に1つだけ」を強制します。

エラーメッセージの読み方

error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
E0502
エラーコード — `rustc --explain E0502` で詳しい説明が見られます
cannot borrow `v` as mutable because it is also borrowed as immutable
詳細メッセージ — 何が問題だったか

このエラーが出る典型パターン

パターン1

 1  fn main() {
 2      let mut v = vec![1, 2, 3];
 3      let first = &v[0];
 4      v.push(4);  
              ^
 5      println!("{}", first);
 6  }
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable

firstというvへの不変参照がまだ使われる予定がある間は、vを変更する可変借用(push)は許されません。

直し方: v.push(4);(空) にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  fn main() {
 2      let mut nums = vec![10, 20, 30];
 3      let head = &nums[0];
 4      nums.push(40); 
               ^
 5      println!("{}", head);
 6  }
error[E0502]: cannot borrow `nums` as mutable because it is also borrowed as immutable

不変参照headが生きている間にnumsをpushで変更しようとすると、借用チェッカーがコンパイル時に止めます。

直し方: nums.push(40);(空) にします。

この問題を解いてみる →

パターン3

 1  fn main() {
 2      let mut names = vec![String::from("a")];
 3      let first_name = &names[0];
 4      names.push(String::from("b"));
                       ^
 5      println!("{}", first_name);
 6  }
error[E0502]: cannot borrow `names` as mutable because it is also borrowed as immutable

不変参照と可変参照は同時に存在できません。参照を使い終わってから変更する必要があります。

直し方: names.push(String::from("b"));(空) にします。

この問題を解いてみる →

パターン4

 1  fn main() {
 2      let mut prices = vec![100, 200];
 3      let cheapest = &prices[0];
 4      prices.push(50);
                ^
 5      println!("{}", cheapest);
 6  }
error[E0502]: cannot borrow `prices` as mutable because it is also borrowed as immutable

参照が有効な間は元のVecへの変更操作(追加や並べ替え)は一切できません。

直し方: prices.push(50);(空) にします。

この問題を解いてみる →

パターン5

 1  fn main() {
 2      let mut scores = vec![70, 80];
 3      let top = &scores[1];
 4      scores.push(90); 
                ^
 5      println!("{}", top);
 6  }
error[E0502]: cannot borrow `scores` as mutable because it is also borrowed as immutable

Vecへの追加は内部でメモリの再確保が起きうるため、既存の参照との共存を許すと危険です。

直し方: scores.push(90);(空) にします。

この問題を解いてみる →

よくある誤解

「参照を作った後でも、元の変数を自由に変更できるはず」という思い込みは誤りです。不変参照がまだ使われる予定がある間は、その変数自体を変更する可変借用は一切できません。

まとめ

E0502: cannot borrow as mutable because it is also borrowed as immutableは中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)