error[E0505]: cannot move out of `var` because it is borrowed
参照中の変数を移動しようとした。
このエラー自体のルールは単純である。
しかし、エラーを読み解くには、参照まわりのその他の知識も必要になる事がある。
例えば、『ライフタイムの延長』の影響があると、初見では納得しにくいエラーになる。
メッセージの構成はだいたい以下のようになる。
clone
の提案
Clone
実装なし)単純に条件を満たした場合について。
fn main() {
let var = MyType();
let var_ref = &var;
var.consume();
var_ref.use_ref();
}
struct MyType();
impl MyType {
pub fn consume(self) {}
pub fn use_ref(&self) {}
}
error[E0505]: cannot move out of `var` because it is borrowed --> src\main.rs:4:5 | 2 | let var = MyType(); | --- binding `var` declared here 3 | let var_ref = &var; | ---- borrow of `var` occurs here 4 | var.consume(); | ^^^ move out of `var` occurs here 5 | var_ref.use_ref(); | ------- borrow later used here | note: if `MyType` implemented `Clone`, you could clone the value --> src\main.rs:8:1 | 3 | let var_ref = &var; | --- you could clone this value ... 8 | struct MyType(); | ^^^^^^^^^^^^^ consider implementing `Clone` for this type
Clone
実装あり)
前のパターンとほぼ同じだが、Clone
を実装済の場合、微妙にメッセージが変わる。
fn main() {
let var = MyType();
let var_ref = &var;
var.consume();
var_ref.use_ref();
}
#[derive(Clone)]
struct MyType();
impl MyType {
pub fn consume(self) {}
pub fn use_ref(&self) {}
}
error[E0505]: cannot move out of `var` because it is borrowed --> src\main.rs:4:5 | 2 | let var = MyType(); | --- binding `var` declared here 3 | let var_ref = &var; | ---- borrow of `var` occurs here 4 | var.consume(); | ^^^ move out of `var` occurs here 5 | var_ref.use_ref(); | ------- borrow later used here | help: consider cloning the value if the performance cost is acceptable | 3 | let var_ref = &var.clone(); | ++++++++
Drop
トレイトの影響
詳しくは『Drop トレイトのライフタイムへの影響 - ライフタイムの延長』を参照。
(注: Drop
トレイトを直接的に扱っていなくても考慮が必要。)
fn main() {
let var = MyValue(1);
let _var_ref = var.new_ref();
var.consume();
}
#[derive(Clone)]
struct MyValue(i32);
impl MyValue {
fn consume(self) {}
fn new_ref(&self) -> MyRef<'_> {
MyRef(&self.0)
}
}
struct MyRef<'a>(&'a i32);
impl Drop for MyRef<'_> {
fn drop(&mut self) {
println!("ID [{}] is drpoped.", self.0)
}
}
error[E0505]: cannot move out of `var` because it is borrowed --> src\main.rs:4:5 | 2 | let var = MyValue(1); | --- binding `var` declared here 3 | let _var_ref = var.new_ref(); | --- borrow of `var` occurs here 4 | var.consume(); | ^^^ move out of `var` occurs here 5 | } | - borrow might be used here, when `_var_ref` is dropped and runs the `Drop` code for type `MyRef` | help: consider cloning the value if the performance cost is acceptable | 3 | let _var_ref = var.clone().new_ref(); | ++++++++