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