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