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パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。