| A borrowed value was moved out. | |
| Erroneous code example: | |
| ```compile_fail,E0507 | |
| use std::cell::RefCell; | |
| struct TheDarkKnight; | |
| impl TheDarkKnight { | |
| fn nothing_is_true(self) {} | |
| } | |
| fn main() { | |
| let x = RefCell::new(TheDarkKnight); | |
| x.borrow().nothing_is_true(); // error: cannot move out of borrowed content | |
| } | |
| ``` | |
| Here, the `nothing_is_true` method takes the ownership of `self`. However, | |
| `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`, | |
| which is a borrow of the content owned by the `RefCell`. To fix this error, | |
| you have three choices: | |
| * Try to avoid moving the variable. | |
| * Somehow reclaim the ownership. | |
| * Implement the `Copy` trait on the type. | |
| This can also happen when using a type implementing `Fn` or `FnMut`, as neither | |
| allows moving out of them (they usually represent closures which can be called | |
| more than once). Much of the text following applies equally well to non-`FnOnce` | |
| closure bodies. | |
| Examples: | |
| ``` | |
| use std::cell::RefCell; | |
| struct TheDarkKnight; | |
| impl TheDarkKnight { | |
| fn nothing_is_true(&self) {} // First case, we don't take ownership | |
| } | |
| fn main() { | |
| let x = RefCell::new(TheDarkKnight); | |
| x.borrow().nothing_is_true(); // ok! | |
| } | |
| ``` | |
| Or: | |
| ``` | |
| use std::cell::RefCell; | |
| struct TheDarkKnight; | |
| impl TheDarkKnight { | |
| fn nothing_is_true(self) {} | |
| } | |
| fn main() { | |
| let x = RefCell::new(TheDarkKnight); | |
| let x = x.into_inner(); // we get back ownership | |
| x.nothing_is_true(); // ok! | |
| } | |
| ``` | |
| Or: | |
| ``` | |
| use std::cell::RefCell; | |
| #[derive(Clone, Copy)] // we implement the Copy trait | |
| struct TheDarkKnight; | |
| impl TheDarkKnight { | |
| fn nothing_is_true(self) {} | |
| } | |
| fn main() { | |
| let x = RefCell::new(TheDarkKnight); | |
| x.borrow().nothing_is_true(); // ok! | |
| } | |
| ``` | |
| Moving a member out of a mutably borrowed struct will also cause E0507 error: | |
| ```compile_fail,E0507 | |
| struct TheDarkKnight; | |
| impl TheDarkKnight { | |
| fn nothing_is_true(self) {} | |
| } | |
| struct Batcave { | |
| knight: TheDarkKnight | |
| } | |
| fn main() { | |
| let mut cave = Batcave { | |
| knight: TheDarkKnight | |
| }; | |
| let borrowed = &mut cave; | |
| borrowed.knight.nothing_is_true(); // E0507 | |
| } | |
| ``` | |
| It is fine only if you put something back. `mem::replace` can be used for that: | |
| ``` | |
| # struct TheDarkKnight; | |
| # impl TheDarkKnight { fn nothing_is_true(self) {} } | |
| # struct Batcave { knight: TheDarkKnight } | |
| use std::mem; | |
| let mut cave = Batcave { | |
| knight: TheDarkKnight | |
| }; | |
| let borrowed = &mut cave; | |
| mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! | |
| ``` | |
| For more information on Rust's ownership system, take a look at the | |
| [References & Borrowing][references-and-borrowing] section of the Book. | |
| [references-and-borrowing]: https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html |