]> git.proxmox.com Git - rustc.git/blame - src/librustc_borrowck/diagnostics.rs
New upstream version 1.19.0+dfsg1
[rustc.git] / src / librustc_borrowck / diagnostics.rs
CommitLineData
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
13register_long_diagnostics! {
14
c1a9b12d
SL
15E0373: r##"
16This error occurs when an attempt is made to use data captured by a closure,
17when that data may no longer exist. It's most commonly seen when attempting to
18return a closure:
19
5bcae85e 20```compile_fail,E0373
c1a9b12d
SL
21fn foo() -> Box<Fn(u32) -> u32> {
22 let x = 0u32;
23 Box::new(|y| x + y)
24}
25```
26
27Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
28closed-over data by reference. This means that once `foo()` returns, `x` no
7453a54e
SL
29longer exists. An attempt to access `x` within the closure would thus be
30unsafe.
c1a9b12d
SL
31
32Another situation where this might be encountered is when spawning threads:
33
5bcae85e 34```compile_fail,E0373
c1a9b12d
SL
35fn foo() {
36 let x = 0u32;
37 let y = 1u32;
38
39 let thr = std::thread::spawn(|| {
40 x + y
41 });
42}
43```
44
45Since our new thread runs in parallel, the stack frame containing `x` and `y`
46may 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
48stack frame won't disappear), we will not succeed: the compiler cannot prove
49that this behaviour is safe, and so won't let us do it.
50
51The solution to this problem is usually to switch to using a `move` closure.
52This approach moves (or copies, where possible) data into the closure, rather
53than taking references to it. For example:
54
55```
56fn foo() -> Box<Fn(u32) -> u32> {
57 let x = 0u32;
58 Box::new(move |y| x + y)
59}
60```
61
62Now that the closure has its own copy of the data, there's no need to worry
63about safety.
64"##,
65
62682a34
SL
66E0381: r##"
67It is not allowed to use or capture an uninitialized variable. For example:
68
5bcae85e 69```compile_fail,E0381
62682a34
SL
70fn main() {
71 let x: i32;
72 let y = x; // error, use of possibly uninitialized variable
7453a54e 73}
62682a34
SL
74```
75
76To fix this, ensure that any declared variables are initialized before being
7453a54e
SL
77used. Example:
78
79```
80fn main() {
81 let x: i32 = 0;
82 let y = x; // ok!
83}
84```
c1a9b12d
SL
85"##,
86
e9174d1e
SL
87E0382: r##"
88This error occurs when an attempt is made to use a variable after its contents
89have been moved elsewhere. For example:
90
5bcae85e 91```compile_fail,E0382
e9174d1e
SL
92struct MyStruct { s: u32 }
93
94fn main() {
95 let mut x = MyStruct{ s: 5u32 };
96 let y = x;
97 x.s = 6;
98 println!("{}", x.s);
99}
100```
101
102Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
103of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
104of workarounds like `Rc`, a value cannot be owned by more than one variable.
105
106If 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
108information in `x`, while leaving the original version owned by `x`. Subsequent
109changes to `x` will not be reflected when accessing `y`.
110
111```
112#[derive(Copy, Clone)]
113struct MyStruct { s: u32 }
114
115fn main() {
116 let mut x = MyStruct{ s: 5u32 };
117 let y = x;
118 x.s = 6;
119 println!("{}", x.s);
120}
121```
122
123Alternatively, if we don't control the struct's definition, or mutable shared
124ownership is truly required, we can use `Rc` and `RefCell`:
125
126```
127use std::cell::RefCell;
128use std::rc::Rc;
129
130struct MyStruct { s: u32 }
131
132fn 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
140With this approach, x and y share ownership of the data via the `Rc` (reference
141count type). `RefCell` essentially performs runtime borrow checking: ensuring
142that at most one writer or multiple readers can access the data at any one time.
143
144If you wish to learn more about ownership in Rust, start with the chapter in the
145Book:
146
147https://doc.rust-lang.org/book/ownership.html
148"##,
149
150E0383: r##"
151This error occurs when an attempt is made to partially reinitialize a
152structure that is currently uninitialized.
153
154For example, this can happen when a drop has taken place:
155
3157f602 156```ignore
7453a54e
SL
157struct Foo {
158 a: u32,
159}
160
e9174d1e
SL
161let mut x = Foo { a: 1 };
162drop(x); // `x` is now uninitialized
163x.a = 2; // error, partial reinitialization of uninitialized structure `t`
164```
165
166This error can be fixed by fully reinitializing the structure in question:
167
168```
7453a54e
SL
169struct Foo {
170 a: u32,
171}
172
e9174d1e
SL
173let mut x = Foo { a: 1 };
174drop(x);
175x = Foo { a: 2 };
176```
177"##,
178
c1a9b12d
SL
179E0384: r##"
180This error occurs when an attempt is made to reassign an immutable variable.
181For example:
182
5bcae85e
SL
183```compile_fail,E0384
184fn main() {
c1a9b12d
SL
185 let x = 3;
186 x = 5; // error, reassignment of immutable variable
187}
188```
189
190By 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 194fn main() {
c1a9b12d
SL
195 let mut x = 3;
196 x = 5;
197}
198```
e9174d1e
SL
199"##,
200
cc61c64b 201/*E0386: r##"
e9174d1e
SL
202This error occurs when an attempt is made to mutate the target of a mutable
203reference stored inside an immutable container.
204
205For example, this can happen when storing a `&mut` inside an immutable `Box`:
206
5bcae85e 207```compile_fail,E0386
e9174d1e
SL
208let mut x: i64 = 1;
209let y: Box<_> = Box::new(&mut x);
210**y = 2; // error, cannot assign to data in an immutable container
211```
212
213This error can be fixed by making the container mutable:
214
215```
216let mut x: i64 = 1;
217let mut y: Box<_> = Box::new(&mut x);
218**y = 2;
219```
220
7453a54e
SL
221It can also be fixed by using a type with interior mutability, such as `Cell`
222or `RefCell`:
e9174d1e
SL
223
224```
7453a54e
SL
225use std::cell::Cell;
226
e9174d1e
SL
227let x: i64 = 1;
228let y: Box<Cell<_>> = Box::new(Cell::new(x));
229y.set(2);
230```
cc61c64b 231"##,*/
e9174d1e
SL
232
233E0387: r##"
234This error occurs when an attempt is made to mutate or mutably reference data
235that 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.
240fn 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...`
244fn 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...`
251fn mut_addr() {
252 let mut x = 0u32;
253 foo(|| { let y = &mut x; });
254}
255```
256
257The problem here is that foo is defined as accepting a parameter of type `Fn`.
258Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
259they capture their context immutably.
260
261If the definition of `foo` is under your control, the simplest solution is to
262capture the data mutably. This can be done by defining `foo` to take FnMut
263rather than Fn:
264
265```
266fn foo<F: FnMut()>(f: F) { }
267```
268
269Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
7453a54e
SL
270interior mutability through a shared reference. Our example's `mutable`
271function could be redefined as below:
e9174d1e
SL
272
273```
274use std::cell::Cell;
275
7453a54e
SL
276fn foo<F: Fn()>(f: F) { }
277
e9174d1e
SL
278fn mutable() {
279 let x = Cell::new(0u32);
280 foo(|| x.set(2));
281}
282```
283
284You can read more about cell types in the API documentation:
285
286https://doc.rust-lang.org/std/cell/
b039eaaf
SL
287"##,
288
5bcae85e 289E0388: r##"
8bb4bdeb 290E0388 was removed and is no longer issued.
5bcae85e
SL
291"##,
292
a7813a04
XL
293E0389: r##"
294An attempt was made to mutate data using a non-mutable reference. This
295commonly occurs when attempting to assign to a non-mutable reference of a
296mutable reference (`&(&mut T)`).
297
298Example of erroneous code:
299
5bcae85e 300```compile_fail,E0389
a7813a04 301struct FancyNum {
5bcae85e 302 num: u8,
a7813a04
XL
303}
304
305fn 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
313Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an
314immutable reference to a value borrows it immutably. There can be multiple
315references of type `&(&mut T)` that point to the same value, so they must be
316immutable to prevent multiple mutable references to the same value.
317
318To fix this, either remove the outer reference:
319
320```
321struct FancyNum {
5bcae85e 322 num: u8,
a7813a04
XL
323}
324
325fn 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
337Or make the outer reference mutable:
338
339```
340struct FancyNum {
341 num: u8
342}
343
344fn 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
357E0499: r##"
358A variable was borrowed as mutable more than once. Erroneous code example:
359
5bcae85e 360```compile_fail,E0499
b039eaaf
SL
361let mut i = 0;
362let mut x = &mut i;
363let mut a = &mut i;
364// error: cannot borrow `i` as mutable more than once at a time
365```
366
367Please note that in rust, you can either have many immutable references, or one
368mutable reference. Take a look at
369https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more
370information. Example:
371
372
373```
374let mut i = 0;
375let mut x = &mut i; // ok!
376
377// or:
378let mut i = 0;
379let a = &i; // ok!
380let b = &i; // still ok!
381let c = &i; // still ok!
382```
383"##,
62682a34 384
a7813a04
XL
385E0500: r##"
386A borrowed variable was used in another closure. Example of erroneous code:
387
388```compile_fail
389fn 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
400In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it
401cannot be borrowed by the `starks` closure at the same time. To fix this issue,
402you can put the closure in its own scope:
403
404```
405fn 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
417Or, if the type implements the `Clone` trait, you can clone it between
418closures:
419
420```
421fn 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
433E0501: r##"
434This error indicates that a mutable variable is being used while it is still
435captured by a closure. Because the closure has borrowed the variable, it is not
436available for use until the closure goes out of scope.
437
438Note that a capture will either move or borrow a variable, but in this
439situation, the closure is borrowing the variable. Take a look at
440http://rustbyexample.com/fn/closures/capture.html for more information about
441capturing.
442
443Example of erroneous code:
444
5bcae85e 445```compile_fail,E0501
a7813a04
XL
446fn inside_closure(x: &mut i32) {
447 // Actions which require unique access
448}
449
450fn outside_closure(x: &mut i32) {
451 // Actions which require unique access
452}
453
454fn 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
463To fix this error, you can place the closure in its own scope:
464
465```
466fn inside_closure(x: &mut i32) {}
467fn outside_closure(x: &mut i32) {}
468
469fn 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
479Or you can pass the variable as a parameter to the closure:
480
481```
482fn inside_closure(x: &mut i32) {}
483fn outside_closure(x: &mut i32) {}
484
485fn 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
494It may be possible to define the closure later:
495
496```
497fn inside_closure(x: &mut i32) {}
498fn outside_closure(x: &mut i32) {}
499
500fn foo(a: &mut i32) {
501 outside_closure(a);
502 let bar = || {
503 inside_closure(a)
504 };
505}
506```
507"##,
508
509E0502: r##"
510This error indicates that you are trying to borrow a variable as mutable when it
511has already been borrowed as immutable.
512
513Example of erroneous code:
514
5bcae85e 515```compile_fail,E0502
a7813a04
XL
516fn bar(x: &mut i32) {}
517fn 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
524To fix this error, ensure that you don't have any other references to the
525variable before trying to access it mutably:
3157f602 526
a7813a04
XL
527```
528fn bar(x: &mut i32) {}
529fn foo(a: &mut i32) {
530 bar(a);
531 let ref y = a; // ok!
532}
533```
3157f602 534
a7813a04
XL
535For more information on the rust ownership system, take a look at
536https://doc.rust-lang.org/stable/book/references-and-borrowing.html.
537"##,
538
3157f602
XL
539E0503: r##"
540A value was used after it was mutably borrowed.
541
542Example of erroneous code:
543
5bcae85e 544```compile_fail,E0503
3157f602
XL
545fn 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
555In this example, `value` is mutably borrowed by `borrow` and cannot be
556used to calculate `sum`. This is not possible because this would violate
557Rust's mutability rules.
558
559You can fix this error by limiting the scope of the borrow:
560
561```
562fn 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
575Or by cloning `value` before borrowing it:
576
577```
578fn 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
591You can find more information about borrowing in the rust-book:
592http://doc.rust-lang.org/stable/book/references-and-borrowing.html
593"##,
594
a7813a04
XL
595E0504: r##"
596This error occurs when an attempt is made to move a borrowed variable into a
597closure.
598
599Example of erroneous code:
600
5bcae85e 601```compile_fail,E0504
a7813a04 602struct FancyNum {
5bcae85e 603 num: u8,
a7813a04
XL
604}
605
606fn 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
620Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into
621the closure `x`. There is no way to move a value into a closure while it is
622borrowed, as that would invalidate the borrow.
623
624If the closure can't outlive the value being moved, try using a reference
625rather than moving:
626
627```
628struct FancyNum {
5bcae85e 629 num: u8,
a7813a04
XL
630}
631
632fn 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
647If the value has to be borrowed and then moved, try limiting the lifetime of
648the borrow using a scoped block:
649
650```
651struct FancyNum {
5bcae85e 652 num: u8,
a7813a04
XL
653}
654
655fn 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
673If the lifetime of a reference isn't enough, such as in the case of threading,
674consider using an `Arc` to create a reference-counted value:
675
676```
677use std::sync::Arc;
678use std::thread;
679
680struct FancyNum {
5bcae85e 681 num: u8,
a7813a04
XL
682}
683
684fn 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
699E0505: r##"
700A value was moved out while it was still borrowed.
701
702Erroneous code example:
703
704```compile_fail,E0505
705struct Value {}
706
707fn eat(val: Value) {}
708
709fn main() {
710 let x = Value{};
711 {
712 let _ref_to_val: &Value = &x;
713 eat(x);
714 }
715}
716```
717
718Here, the function `eat` takes the ownership of `x`. However,
719`x` cannot be moved because it was borrowed to `_ref_to_val`.
720To 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
726Examples:
727
728```
729struct Value {}
730
731fn eat(val: &Value) {}
732
733fn 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
742Or:
743
744```
745struct Value {}
746
747fn eat(val: Value) {}
748
749fn 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
758Or:
759
760```
761#[derive(Clone, Copy)] // implement Copy trait
762struct Value {}
763
764fn eat(val: Value) {}
765
766fn 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
775You can find more information about borrowing in the rust-book:
776http://doc.rust-lang.org/stable/book/references-and-borrowing.html
777"##,
778
a7813a04
XL
779E0506: r##"
780This error occurs when an attempt is made to assign to a borrowed value.
781
782Example of erroneous code:
783
5bcae85e 784```compile_fail,E0506
a7813a04 785struct FancyNum {
5bcae85e 786 num: u8,
a7813a04
XL
787}
788
789fn 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
799Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't
800be assigned to a new value as it would invalidate the reference.
801
802Alternatively, we can move out of `fancy_num` into a second `fancy_num`:
803
804```
805struct FancyNum {
5bcae85e 806 num: u8,
a7813a04
XL
807}
808
809fn 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
818If the value has to be borrowed, try limiting the lifetime of the borrow using
819a scoped block:
820
821```
822struct FancyNum {
5bcae85e 823 num: u8,
a7813a04
XL
824}
825
826fn 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
840Or by moving the reference into a function:
841
842```
843struct FancyNum {
5bcae85e 844 num: u8,
a7813a04
XL
845}
846
847fn 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
857fn print_fancy_ref(fancy_ref: &FancyNum){
858 println!("Ref: {}", fancy_ref.num);
859}
860```
861"##,
862
9cc50fc6
SL
863E0507: r##"
864You tried to move out of a value which was borrowed. Erroneous code example:
865
5bcae85e 866```compile_fail,E0507
9cc50fc6
SL
867use std::cell::RefCell;
868
869struct TheDarkKnight;
870
871impl TheDarkKnight {
872 fn nothing_is_true(self) {}
873}
874
875fn main() {
876 let x = RefCell::new(TheDarkKnight);
877
878 x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
879}
880```
881
882Here, the `nothing_is_true` method takes the ownership of `self`. However,
883`self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
884which is a borrow of the content owned by the `RefCell`. To fix this error,
885you 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
891Examples:
892
893```
894use std::cell::RefCell;
895
896struct TheDarkKnight;
897
898impl TheDarkKnight {
899 fn nothing_is_true(&self) {} // First case, we don't take ownership
900}
901
902fn main() {
903 let x = RefCell::new(TheDarkKnight);
904
905 x.borrow().nothing_is_true(); // ok!
906}
907```
908
909Or:
910
911```
912use std::cell::RefCell;
913
914struct TheDarkKnight;
915
916impl TheDarkKnight {
917 fn nothing_is_true(self) {}
918}
919
920fn 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
928Or:
929
930```
931use std::cell::RefCell;
932
933#[derive(Clone, Copy)] // we implement the Copy trait
934struct TheDarkKnight;
935
936impl TheDarkKnight {
937 fn nothing_is_true(self) {}
938}
939
940fn main() {
941 let x = RefCell::new(TheDarkKnight);
942
943 x.borrow().nothing_is_true(); // ok!
944}
945```
946
7453a54e
SL
947Moving out of a member of a mutably borrowed struct is fine if you put something
948back. `mem::replace` can be used for that:
949
950```ignore
951struct TheDarkKnight;
952
953impl TheDarkKnight {
954 fn nothing_is_true(self) {}
955}
956
957struct Batcave {
958 knight: TheDarkKnight
959}
960
961fn 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
974You can find more information about borrowing in the rust-book:
975http://doc.rust-lang.org/stable/book/references-and-borrowing.html
976"##,
977
3157f602
XL
978E0508: r##"
979A value was moved out of a non-copy fixed-size array.
980
981Example of erroneous code:
982
5bcae85e 983```compile_fail,E0508
3157f602
XL
984struct NonCopy;
985
986fn 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
993The first element was moved out of the array, but this is not
994possible because `NonCopy` does not implement the `Copy` trait.
995
996Consider borrowing the element instead of moving it:
997
998```
999struct NonCopy;
1000
1001fn main() {
1002 let array = [NonCopy; 1];
1003 let _value = &array[0]; // Borrowing is allowed, unlike moving.
1004}
1005```
1006
1007Alternatively, if your type implements `Clone` and you need to own the value,
1008consider borrowing and then cloning:
1009
1010```
1011#[derive(Clone)]
1012struct NonCopy;
1013
1014fn 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
1022E0509: r##"
1023This error occurs when an attempt is made to move out of a value whose type
1024implements the `Drop` trait.
1025
1026Example of erroneous code:
1027
5bcae85e 1028```compile_fail,E0509
a7813a04
XL
1029struct FancyNum {
1030 num: usize
1031}
1032
1033struct DropStruct {
1034 fancy: FancyNum
1035}
1036
1037impl Drop for DropStruct {
1038 fn drop(&mut self) {
1039 // Destruct DropStruct, possibly using FancyNum
1040 }
1041}
1042
1043fn 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
1051Here, we tried to move a field out of a struct of type `DropStruct` which
1052implements the `Drop` trait. However, a struct cannot be dropped if one or
1053more of its fields have been moved.
1054
1055Structs implementing the `Drop` trait have an implicit destructor that gets
1056called when they go out of scope. This destructor may use the fields of the
1057struct, so moving out of the struct could make it impossible to run the
1058destructor. Therefore, we must think of all values whose type implements the
1059`Drop` trait as single units whose fields cannot be moved.
1060
1061This error can be fixed by creating a reference to the fields of a struct,
1062enum, or tuple using the `ref` keyword:
1063
1064```
1065struct FancyNum {
1066 num: usize
1067}
1068
1069struct DropStruct {
1070 fancy: FancyNum
1071}
1072
1073impl Drop for DropStruct {
1074 fn drop(&mut self) {
1075 // Destruct DropStruct, possibly using FancyNum
1076 }
1077}
1078
1079fn 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
1087Note that this technique can also be used in the arms of a match expression:
1088
1089```
1090struct FancyNum {
1091 num: usize
1092}
1093
1094enum DropEnum {
1095 Fancy(FancyNum)
1096}
1097
1098impl Drop for DropEnum {
1099 fn drop(&mut self) {
1100 // Destruct DropEnum, possibly using FancyNum
1101 }
1102}
1103
1104fn 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
1117E0596: r##"
1118This error occurs because you tried to mutably borrow a non-mutable variable.
1119
1120Example of erroneous code:
1121
1122```compile_fail,E0596
1123let x = 1;
1124let y = &mut x; // error: cannot borrow mutably
1125```
1126
1127In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it
1128fails. To fix this error, you need to make `x` mutable:
1129
1130```
1131let mut x = 1;
1132let y = &mut x; // ok!
1133```
1134"##,
1135
1136E0597: r##"
1137This error occurs because a borrow was made inside a variable which has a
1138greater lifetime than the borrowed one.
1139
1140Example of erroneous code:
1141
1142```compile_fail,E0597
1143struct Foo<'a> {
1144 x: Option<&'a u32>,
1145}
1146
1147let mut x = Foo { x: None };
1148let y = 0;
1149x.x = Some(&y); // error: `y` does not live long enough
1150```
1151
1152In here, `x` is created before `y` and therefore has a greater lifetime. Always
1153keep in mind that values in a scope are dropped in the opposite order they are
1154created. So to fix the previous example, just make the `y` lifetime greater than
1155the `x`'s one:
1156
1157```
1158struct Foo<'a> {
1159 x: Option<&'a u32>,
1160}
1161
1162let y = 0;
1163let mut x = Foo { x: None };
1164x.x = Some(&y);
1165```
1166"##,
1167
62682a34
SL
1168}
1169
9346a6ac 1170register_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}