E0382: borrow of moved value(ムーブ後の値の使用)の原因と直し方
StringやVecのようにCopyトレイトを実装しない値を別の変数に代入すると、所有権が移動(ムーブ)します。ムーブ後に元の変数を使おうとすると、コンパイル時にE0382エラーになります。
エラーメッセージの読み方
error[E0382]: borrow of moved value: `s1`
E0382- エラーコード — `rustc --explain E0382` で詳しい説明が見られます
borrow of moved value: `s1`- 詳細メッセージ — 何が問題だったか
このエラーが出る典型パターン
パターン1
1 fn main() { 2 let s1 = String::from("hello"); 3 let s2 = s1 ; ^ 4 println!("{} {}", s1, s2); 5 }
error[E0382]: borrow of moved value: `s1`
s1をそのままs2に代入すると所有権が移動し、s1は無効になります。両方使いたい場合はcloneで複製します。
直し方: s1 を s1.clone() にします。
広告
広告スロット(未設定)
パターン2
1 fn main() { 2 let name1 = String::from("taro"); 3 let name2 = name1 ; ^ 4 println!("{} {}", name1, name2); 5 }
error[E0382]: borrow of moved value: `name1`
Stringのようにヒープにデータを持つ型は、代入すると値がコピーされず所有権だけが移動します。
直し方: name1 を name1.clone() にします。
パターン3
1 fn main() { 2 let title = String::from("report"); 3 let copy = title ; ^ 4 println!("{} {}", title, copy); 5 }
error[E0382]: borrow of moved value: `title`
整数のようなCopy型と違い、Stringは代入のたびに所有権の移動が起こります。
直し方: title を title.clone() にします。
パターン4
1 fn main() { 2 let label = String::from("final"); 3 let backup = label ; ^ 4 println!("{} {}", label, backup); 5 }
error[E0382]: borrow of moved value: `label`
ムーブ後に元の変数を使おうとすると、コンパイラがその場でE0382エラーとして検出します。
直し方: label を label.clone() にします。
パターン5
1 fn main() { 2 let word = String::from("guide"); 3 let alt = word ; ^ 4 println!("{} {}", word, alt); 5 }
error[E0382]: borrow of moved value: `word`
両方の変数を独立して使いたい場合は、複製のコストと引き換えにcloneを使う必要があります。
直し方: word を word.clone() にします。
よくある誤解
「代入は値のコピーだから、元の変数もそのまま使えるはず」という思い込みは誤りです。Copyを実装しない型の代入は所有権の移動であり、元の変数はその時点で無効になります。
まとめ
E0382: borrow of moved value(ムーブ後の値の使用)の原因と直し方は初級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。