]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_error_codes/src/error_codes/E0507.md
Rollup merge of #93556 - dtolnay:trailingcomma, r=cjgillot
[rust.git] / compiler / rustc_error_codes / src / error_codes / E0507.md
1 A borrowed value was moved out.
2
3 Erroneous code example:
4
5 ```compile_fail,E0507
6 use std::cell::RefCell;
7
8 struct TheDarkKnight;
9
10 impl TheDarkKnight {
11     fn nothing_is_true(self) {}
12 }
13
14 fn main() {
15     let x = RefCell::new(TheDarkKnight);
16
17     x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
18 }
19 ```
20
21 Here, the `nothing_is_true` method takes the ownership of `self`. However,
22 `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
23 which is a borrow of the content owned by the `RefCell`. To fix this error,
24 you have three choices:
25
26 * Try to avoid moving the variable.
27 * Somehow reclaim the ownership.
28 * Implement the `Copy` trait on the type.
29
30 This can also happen when using a type implementing `Fn` or `FnMut`, as neither
31 allows moving out of them (they usually represent closures which can be called
32 more than once). Much of the text following applies equally well to non-`FnOnce`
33 closure bodies.
34
35 Examples:
36
37 ```
38 use std::cell::RefCell;
39
40 struct TheDarkKnight;
41
42 impl TheDarkKnight {
43     fn nothing_is_true(&self) {} // First case, we don't take ownership
44 }
45
46 fn main() {
47     let x = RefCell::new(TheDarkKnight);
48
49     x.borrow().nothing_is_true(); // ok!
50 }
51 ```
52
53 Or:
54
55 ```
56 use std::cell::RefCell;
57
58 struct TheDarkKnight;
59
60 impl TheDarkKnight {
61     fn nothing_is_true(self) {}
62 }
63
64 fn main() {
65     let x = RefCell::new(TheDarkKnight);
66     let x = x.into_inner(); // we get back ownership
67
68     x.nothing_is_true(); // ok!
69 }
70 ```
71
72 Or:
73
74 ```
75 use std::cell::RefCell;
76
77 #[derive(Clone, Copy)] // we implement the Copy trait
78 struct TheDarkKnight;
79
80 impl TheDarkKnight {
81     fn nothing_is_true(self) {}
82 }
83
84 fn main() {
85     let x = RefCell::new(TheDarkKnight);
86
87     x.borrow().nothing_is_true(); // ok!
88 }
89 ```
90
91 Moving a member out of a mutably borrowed struct will also cause E0507 error:
92
93 ```compile_fail,E0507
94 struct TheDarkKnight;
95
96 impl TheDarkKnight {
97     fn nothing_is_true(self) {}
98 }
99
100 struct Batcave {
101     knight: TheDarkKnight
102 }
103
104 fn main() {
105     let mut cave = Batcave {
106         knight: TheDarkKnight
107     };
108     let borrowed = &mut cave;
109
110     borrowed.knight.nothing_is_true(); // E0507
111 }
112 ```
113
114 It is fine only if you put something back. `mem::replace` can be used for that:
115
116 ```
117 # struct TheDarkKnight;
118 # impl TheDarkKnight { fn nothing_is_true(self) {} }
119 # struct Batcave { knight: TheDarkKnight }
120 use std::mem;
121
122 let mut cave = Batcave {
123     knight: TheDarkKnight
124 };
125 let borrowed = &mut cave;
126
127 mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok!
128 ```
129
130 For more information on Rust's ownership system, take a look at the
131 [References & Borrowing][references-and-borrowing] section of the Book.
132
133 [references-and-borrowing]: https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html