error[E0502]: cannot borrow `data` as mutable because it is also borrowed as immutable
error[E0502]: cannot borrow `data` as immutable because it is also borrowed as mutable
同じ参照先への不変参照と可変参照は共存できない。このルールはコンパイラによる静的解析や最適化に利用できるだけでなく、取得系操作と更新系操作の分離を促進することで、コードの可読性も高める。
このエラー自体のルールは単純である。
しかし、エラーを読み解くには、参照まわりのその他の知識も必要になる事がある。
例えば、『ライフタイムの延長』の影響があると、初見では納得しにくいエラーになる。
メッセージの構成はだいたい以下のようになる。
(不変参照中の可変参照の場合)
不変参照中に可変参照を行うパターン。
fn main() {
let mut data = 0;
let data_ref = &data;
*&mut data = 1;
println!("{}", data_ref);
}
error[E0502]: cannot borrow `data` as mutable because it is also borrowed as immutable --> src\main.rs:4:6 | 3 | let data_ref = &data; | ----- immutable borrow occurs here 4 | *&mut data = 1; | ^^^^^^^^^ mutable borrow occurs here 5 | println!("{}", data_ref); | -------- immutable borrow later used here
可変参照中に不変参照を行うパターン。
fn main() {
let mut data = 0;
let data_mut = &mut data;
println!("{}", &data);
*data_mut = 1;
}
error[E0502]: cannot borrow `data` as immutable because it is also borrowed as mutable --> src\main.rs:4:20 | 3 | let data_mut = &mut data; | --------- mutable borrow occurs here 4 | println!("{}", &data); | ^^^^^ immutable borrow occurs here 5 | *data_mut = 1; | ------------- mutable borrow later used here
Drop
トレイトの影響
詳しくは『Drop トレイトのライフタイムへの影響 - ライフタイムの延長』を参照。
(注: Drop
トレイトを直接的に扱っていなくても考慮が必要。)
fn main() {
let mut var = 0;
let _refs = MyRef(&var);
*&mut var = 1;
}
struct MyRef<'a>(&'a i32);
impl Drop for MyRef<'_> {
fn drop(&mut self) {
println!("ID [{}] is drpoped.", self.0)
}
}
error[E0502]: cannot borrow `var` as mutable because it is also borrowed as immutable --> src\main.rs:4:6 | 3 | let _refs = MyRef(&var); | ---- immutable borrow occurs here 4 | *&mut var = 1; | ^^^^^^^^ mutable borrow occurs here 5 | } | - immutable borrow might be used here, when `_refs` is dropped and runs the `Drop` code for type `MyRef`