already borrowed: BorrowMutError パニックの原因と直し方
RefCellは借用規則を実行時にチェックする仕組みです。borrow_mut()で可変借用した値がまだ生きている間に、もう一度borrow_mut()やborrow()を呼ぶとパニックします。
エラーメッセージの読み方
thread 'main' panicked at main.rs:6:19:
main.rs- ファイル名
6- 行番号 — 実際にクラッシュした行
19- 列番号
panicked- パニック — 実行時に回復不能な状態になったことを示します。tryやResultで捕まえない限り、そのままプロセスが終了します
already borrowed: BorrowMutError- 詳細メッセージ — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 use std::cell::RefCell; 2 fn main() { 3 let data = RefCell::new(5); 4 let b1 = data.borrow_mut(); 5 ^ 6 let b2 = data.borrow_mut(); 7 println!("{}", b2); 8 }
thread 'main' panicked at main.rs:6:19:
already borrowed: BorrowMutError
b1が生きたまま2回目のborrow_mut()を呼ぶとパニックします。dropで先に借用を終了させる必要があります。
直し方: (空) を drop(b1); にします。
広告
広告スロット(未設定)
パターン2
1 use std::cell::RefCell; 2 fn main() { 3 let counter = RefCell::new(0); 4 let c1 = counter.borrow_mut(); 5 ^ 6 let c2 = counter.borrow_mut(); 7 println!("{}", c2); 8 }
thread 'main' panicked at main.rs:6:22:
already borrowed: BorrowMutError
RefCellは借用ルールを実行時にチェックするため、違反すればコンパイルは通っても実行時にパニックします。
直し方: (空) を drop(c1); にします。
パターン3
1 use std::cell::RefCell; 2 fn main() { 3 let cache = RefCell::new(10); 4 let x1 = cache.borrow_mut(); 5 ^ 6 let x2 = cache.borrow_mut(); 7 println!("{}", x2); 8 }
thread 'main' panicked at main.rs:6:20:
already borrowed: BorrowMutError
1つ目の可変借用を使い終わったら、明示的にdropして解放してから次の借用を行う必要があります。
直し方: (空) を drop(x1); にします。
パターン4
1 use std::cell::RefCell; 2 fn main() { 3 let state = RefCell::new(1); 4 let s1 = state.borrow_mut(); 5 ^ 6 let s2 = state.borrow_mut(); 7 println!("{}", s2); 8 }
thread 'main' panicked at main.rs:6:20:
already borrowed: BorrowMutError
コンパイル時の借用チェックが効かない代わりに、RefCellは違反時に確実にパニックで知らせます。
直し方: (空) を drop(s1); にします。
パターン5
1 use std::cell::RefCell; 2 fn main() { 3 let total = RefCell::new(100); 4 let t1 = total.borrow_mut(); 5 ^ 6 let t2 = total.borrow_mut(); 7 println!("{}", t2); 8 }
thread 'main' panicked at main.rs:6:20:
already borrowed: BorrowMutError
すでに可変借用されている状態でさらに借用しようとすると、already borrowedというパニックになります。
直し方: (空) を drop(t1); にします。
よくある誤解
「RefCellを使えば、借用ルールを気にせず何回でも借用できるはず」という思い込みは誤りです。RefCellはコンパイル時ではなく実行時に借用ルールをチェックする仕組みで、違反すればその場でパニックします。
まとめ
already borrowed: BorrowMutError パニックの原因と直し方は上級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。