]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
9346a6ac | 11 | #![allow(non_snake_case)] |
c34b1796 | 12 | |
62682a34 SL |
13 | register_long_diagnostics! { |
14 | ||
c1a9b12d SL |
15 | E0373: r##" |
16 | This error occurs when an attempt is made to use data captured by a closure, | |
17 | when that data may no longer exist. It's most commonly seen when attempting to | |
18 | return a closure: | |
19 | ||
5bcae85e | 20 | ```compile_fail,E0373 |
c1a9b12d SL |
21 | fn foo() -> Box<Fn(u32) -> u32> { |
22 | let x = 0u32; | |
23 | Box::new(|y| x + y) | |
24 | } | |
25 | ``` | |
26 | ||
27 | Notice that `x` is stack-allocated by `foo()`. By default, Rust captures | |
28 | closed-over data by reference. This means that once `foo()` returns, `x` no | |
7453a54e SL |
29 | longer exists. An attempt to access `x` within the closure would thus be |
30 | unsafe. | |
c1a9b12d SL |
31 | |
32 | Another situation where this might be encountered is when spawning threads: | |
33 | ||
5bcae85e | 34 | ```compile_fail,E0373 |
c1a9b12d SL |
35 | fn foo() { |
36 | let x = 0u32; | |
37 | let y = 1u32; | |
38 | ||
39 | let thr = std::thread::spawn(|| { | |
40 | x + y | |
41 | }); | |
42 | } | |
43 | ``` | |
44 | ||
45 | Since our new thread runs in parallel, the stack frame containing `x` and `y` | |
46 | may well have disappeared by the time we try to use them. Even if we call | |
47 | `thr.join()` within foo (which blocks until `thr` has completed, ensuring the | |
48 | stack frame won't disappear), we will not succeed: the compiler cannot prove | |
49 | that this behaviour is safe, and so won't let us do it. | |
50 | ||
51 | The solution to this problem is usually to switch to using a `move` closure. | |
52 | This approach moves (or copies, where possible) data into the closure, rather | |
53 | than taking references to it. For example: | |
54 | ||
55 | ``` | |
56 | fn foo() -> Box<Fn(u32) -> u32> { | |
57 | let x = 0u32; | |
58 | Box::new(move |y| x + y) | |
59 | } | |
60 | ``` | |
61 | ||
62 | Now that the closure has its own copy of the data, there's no need to worry | |
63 | about safety. | |
64 | "##, | |
65 | ||
62682a34 SL |
66 | E0381: r##" |
67 | It is not allowed to use or capture an uninitialized variable. For example: | |
68 | ||
5bcae85e | 69 | ```compile_fail,E0381 |
62682a34 SL |
70 | fn main() { |
71 | let x: i32; | |
72 | let y = x; // error, use of possibly uninitialized variable | |
7453a54e | 73 | } |
62682a34 SL |
74 | ``` |
75 | ||
76 | To fix this, ensure that any declared variables are initialized before being | |
7453a54e SL |
77 | used. Example: |
78 | ||
79 | ``` | |
80 | fn main() { | |
81 | let x: i32 = 0; | |
82 | let y = x; // ok! | |
83 | } | |
84 | ``` | |
c1a9b12d SL |
85 | "##, |
86 | ||
e9174d1e SL |
87 | E0382: r##" |
88 | This error occurs when an attempt is made to use a variable after its contents | |
89 | have been moved elsewhere. For example: | |
90 | ||
5bcae85e | 91 | ```compile_fail,E0382 |
e9174d1e SL |
92 | struct MyStruct { s: u32 } |
93 | ||
94 | fn main() { | |
95 | let mut x = MyStruct{ s: 5u32 }; | |
96 | let y = x; | |
97 | x.s = 6; | |
98 | println!("{}", x.s); | |
99 | } | |
100 | ``` | |
101 | ||
102 | Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out | |
103 | of `x` when we set `y`. This is fundamental to Rust's ownership system: outside | |
104 | of workarounds like `Rc`, a value cannot be owned by more than one variable. | |
105 | ||
106 | If we own the type, the easiest way to address this problem is to implement | |
107 | `Copy` and `Clone` on it, as shown below. This allows `y` to copy the | |
108 | information in `x`, while leaving the original version owned by `x`. Subsequent | |
109 | changes to `x` will not be reflected when accessing `y`. | |
110 | ||
111 | ``` | |
112 | #[derive(Copy, Clone)] | |
113 | struct MyStruct { s: u32 } | |
114 | ||
115 | fn main() { | |
116 | let mut x = MyStruct{ s: 5u32 }; | |
117 | let y = x; | |
118 | x.s = 6; | |
119 | println!("{}", x.s); | |
120 | } | |
121 | ``` | |
122 | ||
123 | Alternatively, if we don't control the struct's definition, or mutable shared | |
124 | ownership is truly required, we can use `Rc` and `RefCell`: | |
125 | ||
126 | ``` | |
127 | use std::cell::RefCell; | |
128 | use std::rc::Rc; | |
129 | ||
130 | struct MyStruct { s: u32 } | |
131 | ||
132 | fn main() { | |
133 | let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 })); | |
134 | let y = x.clone(); | |
135 | x.borrow_mut().s = 6; | |
7453a54e | 136 | println!("{}", x.borrow().s); |
e9174d1e SL |
137 | } |
138 | ``` | |
139 | ||
140 | With this approach, x and y share ownership of the data via the `Rc` (reference | |
141 | count type). `RefCell` essentially performs runtime borrow checking: ensuring | |
142 | that at most one writer or multiple readers can access the data at any one time. | |
143 | ||
144 | If you wish to learn more about ownership in Rust, start with the chapter in the | |
145 | Book: | |
146 | ||
147 | https://doc.rust-lang.org/book/ownership.html | |
148 | "##, | |
149 | ||
150 | E0383: r##" | |
151 | This error occurs when an attempt is made to partially reinitialize a | |
152 | structure that is currently uninitialized. | |
153 | ||
154 | For example, this can happen when a drop has taken place: | |
155 | ||
3157f602 | 156 | ```ignore |
7453a54e SL |
157 | struct Foo { |
158 | a: u32, | |
159 | } | |
160 | ||
e9174d1e SL |
161 | let mut x = Foo { a: 1 }; |
162 | drop(x); // `x` is now uninitialized | |
163 | x.a = 2; // error, partial reinitialization of uninitialized structure `t` | |
164 | ``` | |
165 | ||
166 | This error can be fixed by fully reinitializing the structure in question: | |
167 | ||
168 | ``` | |
7453a54e SL |
169 | struct Foo { |
170 | a: u32, | |
171 | } | |
172 | ||
e9174d1e SL |
173 | let mut x = Foo { a: 1 }; |
174 | drop(x); | |
175 | x = Foo { a: 2 }; | |
176 | ``` | |
177 | "##, | |
178 | ||
c1a9b12d SL |
179 | E0384: r##" |
180 | This error occurs when an attempt is made to reassign an immutable variable. | |
181 | For example: | |
182 | ||
5bcae85e SL |
183 | ```compile_fail,E0384 |
184 | fn main() { | |
c1a9b12d SL |
185 | let x = 3; |
186 | x = 5; // error, reassignment of immutable variable | |
187 | } | |
188 | ``` | |
189 | ||
190 | By default, variables in Rust are immutable. To fix this error, add the keyword | |
191 | `mut` after the keyword `let` when declaring the variable. For example: | |
192 | ||
193 | ``` | |
5bcae85e | 194 | fn main() { |
c1a9b12d SL |
195 | let mut x = 3; |
196 | x = 5; | |
197 | } | |
198 | ``` | |
e9174d1e SL |
199 | "##, |
200 | ||
201 | E0386: r##" | |
202 | This error occurs when an attempt is made to mutate the target of a mutable | |
203 | reference stored inside an immutable container. | |
204 | ||
205 | For example, this can happen when storing a `&mut` inside an immutable `Box`: | |
206 | ||
5bcae85e | 207 | ```compile_fail,E0386 |
e9174d1e SL |
208 | let mut x: i64 = 1; |
209 | let y: Box<_> = Box::new(&mut x); | |
210 | **y = 2; // error, cannot assign to data in an immutable container | |
211 | ``` | |
212 | ||
213 | This error can be fixed by making the container mutable: | |
214 | ||
215 | ``` | |
216 | let mut x: i64 = 1; | |
217 | let mut y: Box<_> = Box::new(&mut x); | |
218 | **y = 2; | |
219 | ``` | |
220 | ||
7453a54e SL |
221 | It can also be fixed by using a type with interior mutability, such as `Cell` |
222 | or `RefCell`: | |
e9174d1e SL |
223 | |
224 | ``` | |
7453a54e SL |
225 | use std::cell::Cell; |
226 | ||
e9174d1e SL |
227 | let x: i64 = 1; |
228 | let y: Box<Cell<_>> = Box::new(Cell::new(x)); | |
229 | y.set(2); | |
230 | ``` | |
231 | "##, | |
232 | ||
233 | E0387: r##" | |
234 | This error occurs when an attempt is made to mutate or mutably reference data | |
235 | that a closure has captured immutably. Examples of this error are shown below: | |
236 | ||
5bcae85e | 237 | ```compile_fail,E0387 |
e9174d1e SL |
238 | // Accepts a function or a closure that captures its environment immutably. |
239 | // Closures passed to foo will not be able to mutate their closed-over state. | |
240 | fn foo<F: Fn()>(f: F) { } | |
241 | ||
7453a54e | 242 | // Attempts to mutate closed-over data. Error message reads: |
e9174d1e SL |
243 | // `cannot assign to data in a captured outer variable...` |
244 | fn mutable() { | |
245 | let mut x = 0u32; | |
246 | foo(|| x = 2); | |
247 | } | |
248 | ||
249 | // Attempts to take a mutable reference to closed-over data. Error message | |
250 | // reads: `cannot borrow data mutably in a captured outer variable...` | |
251 | fn mut_addr() { | |
252 | let mut x = 0u32; | |
253 | foo(|| { let y = &mut x; }); | |
254 | } | |
255 | ``` | |
256 | ||
257 | The problem here is that foo is defined as accepting a parameter of type `Fn`. | |
258 | Closures passed into foo will thus be inferred to be of type `Fn`, meaning that | |
259 | they capture their context immutably. | |
260 | ||
261 | If the definition of `foo` is under your control, the simplest solution is to | |
262 | capture the data mutably. This can be done by defining `foo` to take FnMut | |
263 | rather than Fn: | |
264 | ||
265 | ``` | |
266 | fn foo<F: FnMut()>(f: F) { } | |
267 | ``` | |
268 | ||
269 | Alternatively, we can consider using the `Cell` and `RefCell` types to achieve | |
7453a54e SL |
270 | interior mutability through a shared reference. Our example's `mutable` |
271 | function could be redefined as below: | |
e9174d1e SL |
272 | |
273 | ``` | |
274 | use std::cell::Cell; | |
275 | ||
7453a54e SL |
276 | fn foo<F: Fn()>(f: F) { } |
277 | ||
e9174d1e SL |
278 | fn mutable() { |
279 | let x = Cell::new(0u32); | |
280 | foo(|| x.set(2)); | |
281 | } | |
282 | ``` | |
283 | ||
284 | You can read more about cell types in the API documentation: | |
285 | ||
286 | https://doc.rust-lang.org/std/cell/ | |
b039eaaf SL |
287 | "##, |
288 | ||
5bcae85e SL |
289 | E0388: r##" |
290 | A mutable borrow was attempted in a static location. | |
291 | ||
292 | Erroneous code example: | |
293 | ||
294 | ```compile_fail,E0388 | |
295 | static X: i32 = 1; | |
296 | ||
297 | static STATIC_REF: &'static mut i32 = &mut X; | |
298 | // error: cannot borrow data mutably in a static location | |
299 | ||
300 | const CONST_REF: &'static mut i32 = &mut X; | |
301 | // error: cannot borrow data mutably in a static location | |
302 | ``` | |
303 | ||
304 | To fix this error, you have to use constant borrow: | |
305 | ||
306 | ``` | |
307 | static X: i32 = 1; | |
308 | ||
309 | static STATIC_REF: &'static i32 = &X; | |
310 | ``` | |
311 | "##, | |
312 | ||
a7813a04 XL |
313 | E0389: r##" |
314 | An attempt was made to mutate data using a non-mutable reference. This | |
315 | commonly occurs when attempting to assign to a non-mutable reference of a | |
316 | mutable reference (`&(&mut T)`). | |
317 | ||
318 | Example of erroneous code: | |
319 | ||
5bcae85e | 320 | ```compile_fail,E0389 |
a7813a04 | 321 | struct FancyNum { |
5bcae85e | 322 | num: u8, |
a7813a04 XL |
323 | } |
324 | ||
325 | fn main() { | |
326 | let mut fancy = FancyNum{ num: 5 }; | |
327 | let fancy_ref = &(&mut fancy); | |
328 | fancy_ref.num = 6; // error: cannot assign to data in a `&` reference | |
329 | println!("{}", fancy_ref.num); | |
330 | } | |
331 | ``` | |
332 | ||
333 | Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an | |
334 | immutable reference to a value borrows it immutably. There can be multiple | |
335 | references of type `&(&mut T)` that point to the same value, so they must be | |
336 | immutable to prevent multiple mutable references to the same value. | |
337 | ||
338 | To fix this, either remove the outer reference: | |
339 | ||
340 | ``` | |
341 | struct FancyNum { | |
5bcae85e | 342 | num: u8, |
a7813a04 XL |
343 | } |
344 | ||
345 | fn main() { | |
346 | let mut fancy = FancyNum{ num: 5 }; | |
347 | ||
348 | let fancy_ref = &mut fancy; | |
349 | // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum) | |
350 | ||
351 | fancy_ref.num = 6; // No error! | |
352 | ||
353 | println!("{}", fancy_ref.num); | |
354 | } | |
355 | ``` | |
356 | ||
357 | Or make the outer reference mutable: | |
358 | ||
359 | ``` | |
360 | struct FancyNum { | |
361 | num: u8 | |
362 | } | |
363 | ||
364 | fn main() { | |
365 | let mut fancy = FancyNum{ num: 5 }; | |
366 | ||
367 | let fancy_ref = &mut (&mut fancy); | |
368 | // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum) | |
369 | ||
370 | fancy_ref.num = 6; // No error! | |
371 | ||
372 | println!("{}", fancy_ref.num); | |
373 | } | |
374 | ``` | |
375 | "##, | |
376 | ||
b039eaaf SL |
377 | E0499: r##" |
378 | A variable was borrowed as mutable more than once. Erroneous code example: | |
379 | ||
5bcae85e | 380 | ```compile_fail,E0499 |
b039eaaf SL |
381 | let mut i = 0; |
382 | let mut x = &mut i; | |
383 | let mut a = &mut i; | |
384 | // error: cannot borrow `i` as mutable more than once at a time | |
385 | ``` | |
386 | ||
387 | Please note that in rust, you can either have many immutable references, or one | |
388 | mutable reference. Take a look at | |
389 | https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more | |
390 | information. Example: | |
391 | ||
392 | ||
393 | ``` | |
394 | let mut i = 0; | |
395 | let mut x = &mut i; // ok! | |
396 | ||
397 | // or: | |
398 | let mut i = 0; | |
399 | let a = &i; // ok! | |
400 | let b = &i; // still ok! | |
401 | let c = &i; // still ok! | |
402 | ``` | |
403 | "##, | |
62682a34 | 404 | |
a7813a04 XL |
405 | E0500: r##" |
406 | A borrowed variable was used in another closure. Example of erroneous code: | |
407 | ||
408 | ```compile_fail | |
409 | fn you_know_nothing(jon_snow: &mut i32) { | |
410 | let nights_watch = || { | |
411 | *jon_snow = 2; | |
412 | }; | |
413 | let starks = || { | |
414 | *jon_snow = 3; // error: closure requires unique access to `jon_snow` | |
415 | // but it is already borrowed | |
416 | }; | |
417 | } | |
418 | ``` | |
419 | ||
420 | In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it | |
421 | cannot be borrowed by the `starks` closure at the same time. To fix this issue, | |
422 | you can put the closure in its own scope: | |
423 | ||
424 | ``` | |
425 | fn you_know_nothing(jon_snow: &mut i32) { | |
426 | { | |
427 | let nights_watch = || { | |
428 | *jon_snow = 2; | |
429 | }; | |
430 | } // At this point, `jon_snow` is free. | |
431 | let starks = || { | |
432 | *jon_snow = 3; | |
433 | }; | |
434 | } | |
435 | ``` | |
436 | ||
437 | Or, if the type implements the `Clone` trait, you can clone it between | |
438 | closures: | |
439 | ||
440 | ``` | |
441 | fn you_know_nothing(jon_snow: &mut i32) { | |
442 | let mut jon_copy = jon_snow.clone(); | |
443 | let nights_watch = || { | |
444 | jon_copy = 2; | |
445 | }; | |
446 | let starks = || { | |
447 | *jon_snow = 3; | |
448 | }; | |
449 | } | |
450 | ``` | |
451 | "##, | |
452 | ||
453 | E0501: r##" | |
454 | This error indicates that a mutable variable is being used while it is still | |
455 | captured by a closure. Because the closure has borrowed the variable, it is not | |
456 | available for use until the closure goes out of scope. | |
457 | ||
458 | Note that a capture will either move or borrow a variable, but in this | |
459 | situation, the closure is borrowing the variable. Take a look at | |
460 | http://rustbyexample.com/fn/closures/capture.html for more information about | |
461 | capturing. | |
462 | ||
463 | Example of erroneous code: | |
464 | ||
5bcae85e | 465 | ```compile_fail,E0501 |
a7813a04 XL |
466 | fn inside_closure(x: &mut i32) { |
467 | // Actions which require unique access | |
468 | } | |
469 | ||
470 | fn outside_closure(x: &mut i32) { | |
471 | // Actions which require unique access | |
472 | } | |
473 | ||
474 | fn foo(a: &mut i32) { | |
475 | let bar = || { | |
476 | inside_closure(a) | |
477 | }; | |
478 | outside_closure(a); // error: cannot borrow `*a` as mutable because previous | |
479 | // closure requires unique access. | |
480 | } | |
481 | ``` | |
482 | ||
483 | To fix this error, you can place the closure in its own scope: | |
484 | ||
485 | ``` | |
486 | fn inside_closure(x: &mut i32) {} | |
487 | fn outside_closure(x: &mut i32) {} | |
488 | ||
489 | fn foo(a: &mut i32) { | |
490 | { | |
491 | let bar = || { | |
492 | inside_closure(a) | |
493 | }; | |
494 | } // borrow on `a` ends. | |
495 | outside_closure(a); // ok! | |
496 | } | |
497 | ``` | |
498 | ||
499 | Or you can pass the variable as a parameter to the closure: | |
500 | ||
501 | ``` | |
502 | fn inside_closure(x: &mut i32) {} | |
503 | fn outside_closure(x: &mut i32) {} | |
504 | ||
505 | fn foo(a: &mut i32) { | |
506 | let bar = |s: &mut i32| { | |
507 | inside_closure(s) | |
508 | }; | |
509 | outside_closure(a); | |
510 | bar(a); | |
511 | } | |
512 | ``` | |
513 | ||
514 | It may be possible to define the closure later: | |
515 | ||
516 | ``` | |
517 | fn inside_closure(x: &mut i32) {} | |
518 | fn outside_closure(x: &mut i32) {} | |
519 | ||
520 | fn foo(a: &mut i32) { | |
521 | outside_closure(a); | |
522 | let bar = || { | |
523 | inside_closure(a) | |
524 | }; | |
525 | } | |
526 | ``` | |
527 | "##, | |
528 | ||
529 | E0502: r##" | |
530 | This error indicates that you are trying to borrow a variable as mutable when it | |
531 | has already been borrowed as immutable. | |
532 | ||
533 | Example of erroneous code: | |
534 | ||
5bcae85e | 535 | ```compile_fail,E0502 |
a7813a04 XL |
536 | fn bar(x: &mut i32) {} |
537 | fn foo(a: &mut i32) { | |
538 | let ref y = a; // a is borrowed as immutable. | |
539 | bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed | |
540 | // as immutable | |
541 | } | |
542 | ``` | |
3157f602 | 543 | |
a7813a04 XL |
544 | To fix this error, ensure that you don't have any other references to the |
545 | variable before trying to access it mutably: | |
3157f602 | 546 | |
a7813a04 XL |
547 | ``` |
548 | fn bar(x: &mut i32) {} | |
549 | fn foo(a: &mut i32) { | |
550 | bar(a); | |
551 | let ref y = a; // ok! | |
552 | } | |
553 | ``` | |
3157f602 | 554 | |
a7813a04 XL |
555 | For more information on the rust ownership system, take a look at |
556 | https://doc.rust-lang.org/stable/book/references-and-borrowing.html. | |
557 | "##, | |
558 | ||
3157f602 XL |
559 | E0503: r##" |
560 | A value was used after it was mutably borrowed. | |
561 | ||
562 | Example of erroneous code: | |
563 | ||
5bcae85e | 564 | ```compile_fail,E0503 |
3157f602 XL |
565 | fn main() { |
566 | let mut value = 3; | |
567 | // Create a mutable borrow of `value`. This borrow | |
568 | // lives until the end of this function. | |
569 | let _borrow = &mut value; | |
570 | let _sum = value + 1; // error: cannot use `value` because | |
571 | // it was mutably borrowed | |
572 | } | |
573 | ``` | |
574 | ||
575 | In this example, `value` is mutably borrowed by `borrow` and cannot be | |
576 | used to calculate `sum`. This is not possible because this would violate | |
577 | Rust's mutability rules. | |
578 | ||
579 | You can fix this error by limiting the scope of the borrow: | |
580 | ||
581 | ``` | |
582 | fn main() { | |
583 | let mut value = 3; | |
584 | // By creating a new block, you can limit the scope | |
585 | // of the reference. | |
586 | { | |
587 | let _borrow = &mut value; // Use `_borrow` inside this block. | |
588 | } | |
589 | // The block has ended and with it the borrow. | |
590 | // You can now use `value` again. | |
591 | let _sum = value + 1; | |
592 | } | |
593 | ``` | |
594 | ||
595 | Or by cloning `value` before borrowing it: | |
596 | ||
597 | ``` | |
598 | fn main() { | |
599 | let mut value = 3; | |
600 | // We clone `value`, creating a copy. | |
601 | let value_cloned = value.clone(); | |
602 | // The mutable borrow is a reference to `value` and | |
603 | // not to `value_cloned`... | |
604 | let _borrow = &mut value; | |
605 | // ... which means we can still use `value_cloned`, | |
606 | let _sum = value_cloned + 1; | |
607 | // even though the borrow only ends here. | |
608 | } | |
609 | ``` | |
610 | ||
611 | You can find more information about borrowing in the rust-book: | |
612 | http://doc.rust-lang.org/stable/book/references-and-borrowing.html | |
613 | "##, | |
614 | ||
a7813a04 XL |
615 | E0504: r##" |
616 | This error occurs when an attempt is made to move a borrowed variable into a | |
617 | closure. | |
618 | ||
619 | Example of erroneous code: | |
620 | ||
5bcae85e | 621 | ```compile_fail,E0504 |
a7813a04 | 622 | struct FancyNum { |
5bcae85e | 623 | num: u8, |
a7813a04 XL |
624 | } |
625 | ||
626 | fn main() { | |
627 | let fancy_num = FancyNum { num: 5 }; | |
628 | let fancy_ref = &fancy_num; | |
629 | ||
630 | let x = move || { | |
631 | println!("child function: {}", fancy_num.num); | |
632 | // error: cannot move `fancy_num` into closure because it is borrowed | |
633 | }; | |
634 | ||
635 | x(); | |
636 | println!("main function: {}", fancy_ref.num); | |
637 | } | |
638 | ``` | |
639 | ||
640 | Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into | |
641 | the closure `x`. There is no way to move a value into a closure while it is | |
642 | borrowed, as that would invalidate the borrow. | |
643 | ||
644 | If the closure can't outlive the value being moved, try using a reference | |
645 | rather than moving: | |
646 | ||
647 | ``` | |
648 | struct FancyNum { | |
5bcae85e | 649 | num: u8, |
a7813a04 XL |
650 | } |
651 | ||
652 | fn main() { | |
653 | let fancy_num = FancyNum { num: 5 }; | |
654 | let fancy_ref = &fancy_num; | |
655 | ||
656 | let x = move || { | |
657 | // fancy_ref is usable here because it doesn't move `fancy_num` | |
658 | println!("child function: {}", fancy_ref.num); | |
659 | }; | |
660 | ||
661 | x(); | |
662 | ||
663 | println!("main function: {}", fancy_num.num); | |
664 | } | |
665 | ``` | |
666 | ||
667 | If the value has to be borrowed and then moved, try limiting the lifetime of | |
668 | the borrow using a scoped block: | |
669 | ||
670 | ``` | |
671 | struct FancyNum { | |
5bcae85e | 672 | num: u8, |
a7813a04 XL |
673 | } |
674 | ||
675 | fn main() { | |
676 | let fancy_num = FancyNum { num: 5 }; | |
677 | ||
678 | { | |
679 | let fancy_ref = &fancy_num; | |
680 | println!("main function: {}", fancy_ref.num); | |
681 | // `fancy_ref` goes out of scope here | |
682 | } | |
683 | ||
684 | let x = move || { | |
685 | // `fancy_num` can be moved now (no more references exist) | |
686 | println!("child function: {}", fancy_num.num); | |
687 | }; | |
688 | ||
689 | x(); | |
690 | } | |
691 | ``` | |
692 | ||
693 | If the lifetime of a reference isn't enough, such as in the case of threading, | |
694 | consider using an `Arc` to create a reference-counted value: | |
695 | ||
696 | ``` | |
697 | use std::sync::Arc; | |
698 | use std::thread; | |
699 | ||
700 | struct FancyNum { | |
5bcae85e | 701 | num: u8, |
a7813a04 XL |
702 | } |
703 | ||
704 | fn main() { | |
705 | let fancy_ref1 = Arc::new(FancyNum { num: 5 }); | |
706 | let fancy_ref2 = fancy_ref1.clone(); | |
707 | ||
708 | let x = thread::spawn(move || { | |
709 | // `fancy_ref1` can be moved and has a `'static` lifetime | |
710 | println!("child thread: {}", fancy_ref1.num); | |
711 | }); | |
712 | ||
713 | x.join().expect("child thread should finish"); | |
714 | println!("main thread: {}", fancy_ref2.num); | |
715 | } | |
716 | ``` | |
717 | "##, | |
718 | ||
5bcae85e SL |
719 | E0505: r##" |
720 | A value was moved out while it was still borrowed. | |
721 | ||
722 | Erroneous code example: | |
723 | ||
724 | ```compile_fail,E0505 | |
725 | struct Value {} | |
726 | ||
727 | fn eat(val: Value) {} | |
728 | ||
729 | fn main() { | |
730 | let x = Value{}; | |
731 | { | |
732 | let _ref_to_val: &Value = &x; | |
733 | eat(x); | |
734 | } | |
735 | } | |
736 | ``` | |
737 | ||
738 | Here, the function `eat` takes the ownership of `x`. However, | |
739 | `x` cannot be moved because it was borrowed to `_ref_to_val`. | |
740 | To fix that you can do few different things: | |
741 | ||
742 | * Try to avoid moving the variable. | |
743 | * Release borrow before move. | |
744 | * Implement the `Copy` trait on the type. | |
745 | ||
746 | Examples: | |
747 | ||
748 | ``` | |
749 | struct Value {} | |
750 | ||
751 | fn eat(val: &Value) {} | |
752 | ||
753 | fn main() { | |
754 | let x = Value{}; | |
755 | { | |
756 | let _ref_to_val: &Value = &x; | |
757 | eat(&x); // pass by reference, if it's possible | |
758 | } | |
759 | } | |
760 | ``` | |
761 | ||
762 | Or: | |
763 | ||
764 | ``` | |
765 | struct Value {} | |
766 | ||
767 | fn eat(val: Value) {} | |
768 | ||
769 | fn main() { | |
770 | let x = Value{}; | |
771 | { | |
772 | let _ref_to_val: &Value = &x; | |
773 | } | |
774 | eat(x); // release borrow and then move it. | |
775 | } | |
776 | ``` | |
777 | ||
778 | Or: | |
779 | ||
780 | ``` | |
781 | #[derive(Clone, Copy)] // implement Copy trait | |
782 | struct Value {} | |
783 | ||
784 | fn eat(val: Value) {} | |
785 | ||
786 | fn main() { | |
787 | let x = Value{}; | |
788 | { | |
789 | let _ref_to_val: &Value = &x; | |
790 | eat(x); // it will be copied here. | |
791 | } | |
792 | } | |
793 | ``` | |
794 | ||
795 | You can find more information about borrowing in the rust-book: | |
796 | http://doc.rust-lang.org/stable/book/references-and-borrowing.html | |
797 | "##, | |
798 | ||
a7813a04 XL |
799 | E0506: r##" |
800 | This error occurs when an attempt is made to assign to a borrowed value. | |
801 | ||
802 | Example of erroneous code: | |
803 | ||
5bcae85e | 804 | ```compile_fail,E0506 |
a7813a04 | 805 | struct FancyNum { |
5bcae85e | 806 | num: u8, |
a7813a04 XL |
807 | } |
808 | ||
809 | fn main() { | |
810 | let mut fancy_num = FancyNum { num: 5 }; | |
811 | let fancy_ref = &fancy_num; | |
812 | fancy_num = FancyNum { num: 6 }; | |
813 | // error: cannot assign to `fancy_num` because it is borrowed | |
814 | ||
815 | println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); | |
816 | } | |
817 | ``` | |
818 | ||
819 | Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't | |
820 | be assigned to a new value as it would invalidate the reference. | |
821 | ||
822 | Alternatively, we can move out of `fancy_num` into a second `fancy_num`: | |
823 | ||
824 | ``` | |
825 | struct FancyNum { | |
5bcae85e | 826 | num: u8, |
a7813a04 XL |
827 | } |
828 | ||
829 | fn main() { | |
830 | let mut fancy_num = FancyNum { num: 5 }; | |
831 | let moved_num = fancy_num; | |
832 | fancy_num = FancyNum { num: 6 }; | |
833 | ||
834 | println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num); | |
835 | } | |
836 | ``` | |
837 | ||
838 | If the value has to be borrowed, try limiting the lifetime of the borrow using | |
839 | a scoped block: | |
840 | ||
841 | ``` | |
842 | struct FancyNum { | |
5bcae85e | 843 | num: u8, |
a7813a04 XL |
844 | } |
845 | ||
846 | fn main() { | |
847 | let mut fancy_num = FancyNum { num: 5 }; | |
848 | ||
849 | { | |
850 | let fancy_ref = &fancy_num; | |
851 | println!("Ref: {}", fancy_ref.num); | |
852 | } | |
853 | ||
854 | // Works because `fancy_ref` is no longer in scope | |
855 | fancy_num = FancyNum { num: 6 }; | |
856 | println!("Num: {}", fancy_num.num); | |
857 | } | |
858 | ``` | |
859 | ||
860 | Or by moving the reference into a function: | |
861 | ||
862 | ``` | |
863 | struct FancyNum { | |
5bcae85e | 864 | num: u8, |
a7813a04 XL |
865 | } |
866 | ||
867 | fn main() { | |
868 | let mut fancy_num = FancyNum { num: 5 }; | |
869 | ||
870 | print_fancy_ref(&fancy_num); | |
871 | ||
872 | // Works because function borrow has ended | |
873 | fancy_num = FancyNum { num: 6 }; | |
874 | println!("Num: {}", fancy_num.num); | |
875 | } | |
876 | ||
877 | fn print_fancy_ref(fancy_ref: &FancyNum){ | |
878 | println!("Ref: {}", fancy_ref.num); | |
879 | } | |
880 | ``` | |
881 | "##, | |
882 | ||
9cc50fc6 SL |
883 | E0507: r##" |
884 | You tried to move out of a value which was borrowed. Erroneous code example: | |
885 | ||
5bcae85e | 886 | ```compile_fail,E0507 |
9cc50fc6 SL |
887 | use std::cell::RefCell; |
888 | ||
889 | struct TheDarkKnight; | |
890 | ||
891 | impl TheDarkKnight { | |
892 | fn nothing_is_true(self) {} | |
893 | } | |
894 | ||
895 | fn main() { | |
896 | let x = RefCell::new(TheDarkKnight); | |
897 | ||
898 | x.borrow().nothing_is_true(); // error: cannot move out of borrowed content | |
899 | } | |
900 | ``` | |
901 | ||
902 | Here, the `nothing_is_true` method takes the ownership of `self`. However, | |
903 | `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`, | |
904 | which is a borrow of the content owned by the `RefCell`. To fix this error, | |
905 | you have three choices: | |
906 | ||
907 | * Try to avoid moving the variable. | |
908 | * Somehow reclaim the ownership. | |
909 | * Implement the `Copy` trait on the type. | |
910 | ||
911 | Examples: | |
912 | ||
913 | ``` | |
914 | use std::cell::RefCell; | |
915 | ||
916 | struct TheDarkKnight; | |
917 | ||
918 | impl TheDarkKnight { | |
919 | fn nothing_is_true(&self) {} // First case, we don't take ownership | |
920 | } | |
921 | ||
922 | fn main() { | |
923 | let x = RefCell::new(TheDarkKnight); | |
924 | ||
925 | x.borrow().nothing_is_true(); // ok! | |
926 | } | |
927 | ``` | |
928 | ||
929 | Or: | |
930 | ||
931 | ``` | |
932 | use std::cell::RefCell; | |
933 | ||
934 | struct TheDarkKnight; | |
935 | ||
936 | impl TheDarkKnight { | |
937 | fn nothing_is_true(self) {} | |
938 | } | |
939 | ||
940 | fn main() { | |
941 | let x = RefCell::new(TheDarkKnight); | |
942 | let x = x.into_inner(); // we get back ownership | |
943 | ||
944 | x.nothing_is_true(); // ok! | |
945 | } | |
946 | ``` | |
947 | ||
948 | Or: | |
949 | ||
950 | ``` | |
951 | use std::cell::RefCell; | |
952 | ||
953 | #[derive(Clone, Copy)] // we implement the Copy trait | |
954 | struct TheDarkKnight; | |
955 | ||
956 | impl TheDarkKnight { | |
957 | fn nothing_is_true(self) {} | |
958 | } | |
959 | ||
960 | fn main() { | |
961 | let x = RefCell::new(TheDarkKnight); | |
962 | ||
963 | x.borrow().nothing_is_true(); // ok! | |
964 | } | |
965 | ``` | |
966 | ||
7453a54e SL |
967 | Moving out of a member of a mutably borrowed struct is fine if you put something |
968 | back. `mem::replace` can be used for that: | |
969 | ||
970 | ```ignore | |
971 | struct TheDarkKnight; | |
972 | ||
973 | impl TheDarkKnight { | |
974 | fn nothing_is_true(self) {} | |
975 | } | |
976 | ||
977 | struct Batcave { | |
978 | knight: TheDarkKnight | |
979 | } | |
980 | ||
981 | fn main() { | |
982 | use std::mem; | |
983 | ||
984 | let mut cave = Batcave { | |
985 | knight: TheDarkKnight | |
986 | }; | |
987 | let borrowed = &mut cave; | |
988 | ||
989 | borrowed.knight.nothing_is_true(); // E0507 | |
990 | mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! | |
991 | } | |
992 | ``` | |
993 | ||
9cc50fc6 SL |
994 | You can find more information about borrowing in the rust-book: |
995 | http://doc.rust-lang.org/stable/book/references-and-borrowing.html | |
996 | "##, | |
997 | ||
3157f602 XL |
998 | E0508: r##" |
999 | A value was moved out of a non-copy fixed-size array. | |
1000 | ||
1001 | Example of erroneous code: | |
1002 | ||
5bcae85e | 1003 | ```compile_fail,E0508 |
3157f602 XL |
1004 | struct NonCopy; |
1005 | ||
1006 | fn main() { | |
1007 | let array = [NonCopy; 1]; | |
1008 | let _value = array[0]; // error: cannot move out of type `[NonCopy; 1]`, | |
1009 | // a non-copy fixed-size array | |
1010 | } | |
1011 | ``` | |
1012 | ||
1013 | The first element was moved out of the array, but this is not | |
1014 | possible because `NonCopy` does not implement the `Copy` trait. | |
1015 | ||
1016 | Consider borrowing the element instead of moving it: | |
1017 | ||
1018 | ``` | |
1019 | struct NonCopy; | |
1020 | ||
1021 | fn main() { | |
1022 | let array = [NonCopy; 1]; | |
1023 | let _value = &array[0]; // Borrowing is allowed, unlike moving. | |
1024 | } | |
1025 | ``` | |
1026 | ||
1027 | Alternatively, if your type implements `Clone` and you need to own the value, | |
1028 | consider borrowing and then cloning: | |
1029 | ||
1030 | ``` | |
1031 | #[derive(Clone)] | |
1032 | struct NonCopy; | |
1033 | ||
1034 | fn main() { | |
1035 | let array = [NonCopy; 1]; | |
1036 | // Now you can clone the array element. | |
1037 | let _value = array[0].clone(); | |
1038 | } | |
1039 | ``` | |
1040 | "##, | |
1041 | ||
a7813a04 XL |
1042 | E0509: r##" |
1043 | This error occurs when an attempt is made to move out of a value whose type | |
1044 | implements the `Drop` trait. | |
1045 | ||
1046 | Example of erroneous code: | |
1047 | ||
5bcae85e | 1048 | ```compile_fail,E0509 |
a7813a04 XL |
1049 | struct FancyNum { |
1050 | num: usize | |
1051 | } | |
1052 | ||
1053 | struct DropStruct { | |
1054 | fancy: FancyNum | |
1055 | } | |
1056 | ||
1057 | impl Drop for DropStruct { | |
1058 | fn drop(&mut self) { | |
1059 | // Destruct DropStruct, possibly using FancyNum | |
1060 | } | |
1061 | } | |
1062 | ||
1063 | fn main() { | |
1064 | let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; | |
1065 | let fancy_field = drop_struct.fancy; // Error E0509 | |
1066 | println!("Fancy: {}", fancy_field.num); | |
1067 | // implicit call to `drop_struct.drop()` as drop_struct goes out of scope | |
1068 | } | |
1069 | ``` | |
1070 | ||
1071 | Here, we tried to move a field out of a struct of type `DropStruct` which | |
1072 | implements the `Drop` trait. However, a struct cannot be dropped if one or | |
1073 | more of its fields have been moved. | |
1074 | ||
1075 | Structs implementing the `Drop` trait have an implicit destructor that gets | |
1076 | called when they go out of scope. This destructor may use the fields of the | |
1077 | struct, so moving out of the struct could make it impossible to run the | |
1078 | destructor. Therefore, we must think of all values whose type implements the | |
1079 | `Drop` trait as single units whose fields cannot be moved. | |
1080 | ||
1081 | This error can be fixed by creating a reference to the fields of a struct, | |
1082 | enum, or tuple using the `ref` keyword: | |
1083 | ||
1084 | ``` | |
1085 | struct FancyNum { | |
1086 | num: usize | |
1087 | } | |
1088 | ||
1089 | struct DropStruct { | |
1090 | fancy: FancyNum | |
1091 | } | |
1092 | ||
1093 | impl Drop for DropStruct { | |
1094 | fn drop(&mut self) { | |
1095 | // Destruct DropStruct, possibly using FancyNum | |
1096 | } | |
1097 | } | |
1098 | ||
1099 | fn main() { | |
1100 | let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; | |
1101 | let ref fancy_field = drop_struct.fancy; // No more errors! | |
1102 | println!("Fancy: {}", fancy_field.num); | |
1103 | // implicit call to `drop_struct.drop()` as drop_struct goes out of scope | |
1104 | } | |
1105 | ``` | |
1106 | ||
1107 | Note that this technique can also be used in the arms of a match expression: | |
1108 | ||
1109 | ``` | |
1110 | struct FancyNum { | |
1111 | num: usize | |
1112 | } | |
1113 | ||
1114 | enum DropEnum { | |
1115 | Fancy(FancyNum) | |
1116 | } | |
1117 | ||
1118 | impl Drop for DropEnum { | |
1119 | fn drop(&mut self) { | |
1120 | // Destruct DropEnum, possibly using FancyNum | |
1121 | } | |
1122 | } | |
1123 | ||
1124 | fn main() { | |
1125 | // Creates and enum of type `DropEnum`, which implements `Drop` | |
1126 | let drop_enum = DropEnum::Fancy(FancyNum{num: 10}); | |
1127 | match drop_enum { | |
1128 | // Creates a reference to the inside of `DropEnum::Fancy` | |
1129 | DropEnum::Fancy(ref fancy_field) => // No error! | |
1130 | println!("It was fancy-- {}!", fancy_field.num), | |
1131 | } | |
1132 | // implicit call to `drop_enum.drop()` as drop_enum goes out of scope | |
1133 | } | |
1134 | ``` | |
1135 | "##, | |
1136 | ||
62682a34 SL |
1137 | } |
1138 | ||
9346a6ac | 1139 | register_diagnostics! { |
62682a34 | 1140 | E0385, // {} in an aliasable location |
a7813a04 | 1141 | E0524, // two closures require unique access to `..` at the same time |
223e47cc | 1142 | } |