summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_error_codes/src/error_codes/E0507.md
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_error_codes/src/error_codes/E0507.md')
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0507.md133
1 files changed, 133 insertions, 0 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0507.md b/compiler/rustc_error_codes/src/error_codes/E0507.md
new file mode 100644
index 000000000..254751fc4
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0507.md
@@ -0,0 +1,133 @@
+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