]> git.lizzy.rs Git - rust.git/blob - src/librustc_error_codes/error_codes/E0507.md
Rollup merge of #67943 - Stromberg90:patch-1, r=jonas-schievink
[rust.git] / src / librustc_error_codes / error_codes / E0507.md
1 You tried to move out of a value which was borrowed.
2
3 This can also happen when using a type implementing `Fn` or `FnMut`, as neither
4 allows moving out of them (they usually represent closures which can be called
5 more than once). Much of the text following applies equally well to non-`FnOnce`
6 closure bodies.
7
8 Erroneous code example:
9
10 ```compile_fail,E0507
11 use std::cell::RefCell;
12
13 struct TheDarkKnight;
14
15 impl TheDarkKnight {
16     fn nothing_is_true(self) {}
17 }
18
19 fn main() {
20     let x = RefCell::new(TheDarkKnight);
21
22     x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
23 }
24 ```
25
26 Here, the `nothing_is_true` method takes the ownership of `self`. However,
27 `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
28 which is a borrow of the content owned by the `RefCell`. To fix this error,
29 you have three choices:
30
31 * Try to avoid moving the variable.
32 * Somehow reclaim the ownership.
33 * Implement the `Copy` trait on the type.
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 You can find more information about borrowing in the rust-book:
131 http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html