]> git.proxmox.com Git - rustc.git/blame - src/librustc_borrowck/diagnostics.rs
New upstream version 1.20.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
041b39d2 147https://doc.rust-lang.org/book/first-edition/ownership.html
e9174d1e
SL
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
041b39d2 156```compile_fail,E0383
7453a54e
SL
157struct Foo {
158 a: u32,
159}
041b39d2
XL
160impl Drop for Foo {
161 fn drop(&mut self) { /* ... */ }
162}
7453a54e 163
e9174d1e
SL
164let mut x = Foo { a: 1 };
165drop(x); // `x` is now uninitialized
166x.a = 2; // error, partial reinitialization of uninitialized structure `t`
167```
168
169This error can be fixed by fully reinitializing the structure in question:
170
171```
7453a54e
SL
172struct Foo {
173 a: u32,
174}
041b39d2
XL
175impl Drop for Foo {
176 fn drop(&mut self) { /* ... */ }
177}
7453a54e 178
e9174d1e
SL
179let mut x = Foo { a: 1 };
180drop(x);
181x = Foo { a: 2 };
182```
183"##,
184
c1a9b12d
SL
185E0384: r##"
186This error occurs when an attempt is made to reassign an immutable variable.
187For example:
188
5bcae85e
SL
189```compile_fail,E0384
190fn main() {
c1a9b12d
SL
191 let x = 3;
192 x = 5; // error, reassignment of immutable variable
193}
194```
195
196By 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 200fn main() {
c1a9b12d
SL
201 let mut x = 3;
202 x = 5;
203}
204```
e9174d1e
SL
205"##,
206
cc61c64b 207/*E0386: r##"
e9174d1e
SL
208This error occurs when an attempt is made to mutate the target of a mutable
209reference stored inside an immutable container.
210
211For example, this can happen when storing a `&mut` inside an immutable `Box`:
212
5bcae85e 213```compile_fail,E0386
e9174d1e
SL
214let mut x: i64 = 1;
215let y: Box<_> = Box::new(&mut x);
216**y = 2; // error, cannot assign to data in an immutable container
217```
218
219This error can be fixed by making the container mutable:
220
221```
222let mut x: i64 = 1;
223let mut y: Box<_> = Box::new(&mut x);
224**y = 2;
225```
226
7453a54e
SL
227It can also be fixed by using a type with interior mutability, such as `Cell`
228or `RefCell`:
e9174d1e
SL
229
230```
7453a54e
SL
231use std::cell::Cell;
232
e9174d1e
SL
233let x: i64 = 1;
234let y: Box<Cell<_>> = Box::new(Cell::new(x));
235y.set(2);
236```
cc61c64b 237"##,*/
e9174d1e
SL
238
239E0387: r##"
240This error occurs when an attempt is made to mutate or mutably reference data
241that 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.
246fn 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...`
250fn 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...`
257fn mut_addr() {
258 let mut x = 0u32;
259 foo(|| { let y = &mut x; });
260}
261```
262
263The problem here is that foo is defined as accepting a parameter of type `Fn`.
264Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
265they capture their context immutably.
266
267If the definition of `foo` is under your control, the simplest solution is to
268capture the data mutably. This can be done by defining `foo` to take FnMut
269rather than Fn:
270
271```
272fn foo<F: FnMut()>(f: F) { }
273```
274
275Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
7453a54e
SL
276interior mutability through a shared reference. Our example's `mutable`
277function could be redefined as below:
e9174d1e
SL
278
279```
280use std::cell::Cell;
281
7453a54e
SL
282fn foo<F: Fn()>(f: F) { }
283
e9174d1e
SL
284fn mutable() {
285 let x = Cell::new(0u32);
286 foo(|| x.set(2));
287}
288```
289
290You can read more about cell types in the API documentation:
291
292https://doc.rust-lang.org/std/cell/
b039eaaf
SL
293"##,
294
5bcae85e 295E0388: r##"
8bb4bdeb 296E0388 was removed and is no longer issued.
5bcae85e
SL
297"##,
298
a7813a04
XL
299E0389: r##"
300An attempt was made to mutate data using a non-mutable reference. This
301commonly occurs when attempting to assign to a non-mutable reference of a
302mutable reference (`&(&mut T)`).
303
304Example of erroneous code:
305
5bcae85e 306```compile_fail,E0389
a7813a04 307struct FancyNum {
5bcae85e 308 num: u8,
a7813a04
XL
309}
310
311fn 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
319Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an
320immutable reference to a value borrows it immutably. There can be multiple
321references of type `&(&mut T)` that point to the same value, so they must be
322immutable to prevent multiple mutable references to the same value.
323
324To fix this, either remove the outer reference:
325
326```
327struct FancyNum {
5bcae85e 328 num: u8,
a7813a04
XL
329}
330
331fn 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
343Or make the outer reference mutable:
344
345```
346struct FancyNum {
347 num: u8
348}
349
350fn 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
363E0499: r##"
364A variable was borrowed as mutable more than once. Erroneous code example:
365
5bcae85e 366```compile_fail,E0499
b039eaaf
SL
367let mut i = 0;
368let mut x = &mut i;
369let mut a = &mut i;
370// error: cannot borrow `i` as mutable more than once at a time
371```
372
373Please note that in rust, you can either have many immutable references, or one
374mutable reference. Take a look at
041b39d2
XL
375https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
376for more information. Example:
b039eaaf
SL
377
378
379```
380let mut i = 0;
381let mut x = &mut i; // ok!
382
383// or:
384let mut i = 0;
385let a = &i; // ok!
386let b = &i; // still ok!
387let c = &i; // still ok!
388```
389"##,
62682a34 390
a7813a04
XL
391E0500: r##"
392A borrowed variable was used in another closure. Example of erroneous code:
393
394```compile_fail
395fn 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
406In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it
407cannot be borrowed by the `starks` closure at the same time. To fix this issue,
408you can put the closure in its own scope:
409
410```
411fn 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
423Or, if the type implements the `Clone` trait, you can clone it between
424closures:
425
426```
427fn 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
439E0501: r##"
440This error indicates that a mutable variable is being used while it is still
441captured by a closure. Because the closure has borrowed the variable, it is not
442available for use until the closure goes out of scope.
443
444Note that a capture will either move or borrow a variable, but in this
445situation, the closure is borrowing the variable. Take a look at
446http://rustbyexample.com/fn/closures/capture.html for more information about
447capturing.
448
449Example of erroneous code:
450
5bcae85e 451```compile_fail,E0501
a7813a04
XL
452fn inside_closure(x: &mut i32) {
453 // Actions which require unique access
454}
455
456fn outside_closure(x: &mut i32) {
457 // Actions which require unique access
458}
459
460fn 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
469To fix this error, you can place the closure in its own scope:
470
471```
472fn inside_closure(x: &mut i32) {}
473fn outside_closure(x: &mut i32) {}
474
475fn 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
485Or you can pass the variable as a parameter to the closure:
486
487```
488fn inside_closure(x: &mut i32) {}
489fn outside_closure(x: &mut i32) {}
490
491fn 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
500It may be possible to define the closure later:
501
502```
503fn inside_closure(x: &mut i32) {}
504fn outside_closure(x: &mut i32) {}
505
506fn foo(a: &mut i32) {
507 outside_closure(a);
508 let bar = || {
509 inside_closure(a)
510 };
511}
512```
513"##,
514
515E0502: r##"
516This error indicates that you are trying to borrow a variable as mutable when it
517has already been borrowed as immutable.
518
519Example of erroneous code:
520
5bcae85e 521```compile_fail,E0502
a7813a04
XL
522fn bar(x: &mut i32) {}
523fn 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
530To fix this error, ensure that you don't have any other references to the
531variable before trying to access it mutably:
3157f602 532
a7813a04
XL
533```
534fn bar(x: &mut i32) {}
535fn foo(a: &mut i32) {
536 bar(a);
537 let ref y = a; // ok!
538}
539```
3157f602 540
a7813a04 541For more information on the rust ownership system, take a look at
041b39d2 542https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html.
a7813a04
XL
543"##,
544
3157f602
XL
545E0503: r##"
546A value was used after it was mutably borrowed.
547
548Example of erroneous code:
549
5bcae85e 550```compile_fail,E0503
3157f602
XL
551fn 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
561In this example, `value` is mutably borrowed by `borrow` and cannot be
562used to calculate `sum`. This is not possible because this would violate
563Rust's mutability rules.
564
565You can fix this error by limiting the scope of the borrow:
566
567```
568fn 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
581Or by cloning `value` before borrowing it:
582
583```
584fn 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
597You can find more information about borrowing in the rust-book:
041b39d2 598http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
3157f602
XL
599"##,
600
a7813a04
XL
601E0504: r##"
602This error occurs when an attempt is made to move a borrowed variable into a
603closure.
604
605Example of erroneous code:
606
5bcae85e 607```compile_fail,E0504
a7813a04 608struct FancyNum {
5bcae85e 609 num: u8,
a7813a04
XL
610}
611
612fn 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
626Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into
627the closure `x`. There is no way to move a value into a closure while it is
628borrowed, as that would invalidate the borrow.
629
630If the closure can't outlive the value being moved, try using a reference
631rather than moving:
632
633```
634struct FancyNum {
5bcae85e 635 num: u8,
a7813a04
XL
636}
637
638fn 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
653If the value has to be borrowed and then moved, try limiting the lifetime of
654the borrow using a scoped block:
655
656```
657struct FancyNum {
5bcae85e 658 num: u8,
a7813a04
XL
659}
660
661fn 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
679If the lifetime of a reference isn't enough, such as in the case of threading,
680consider using an `Arc` to create a reference-counted value:
681
682```
683use std::sync::Arc;
684use std::thread;
685
686struct FancyNum {
5bcae85e 687 num: u8,
a7813a04
XL
688}
689
690fn 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
705E0505: r##"
706A value was moved out while it was still borrowed.
707
708Erroneous code example:
709
710```compile_fail,E0505
711struct Value {}
712
713fn eat(val: Value) {}
714
715fn main() {
716 let x = Value{};
717 {
718 let _ref_to_val: &Value = &x;
719 eat(x);
720 }
721}
722```
723
724Here, the function `eat` takes the ownership of `x`. However,
725`x` cannot be moved because it was borrowed to `_ref_to_val`.
726To 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
732Examples:
733
734```
735struct Value {}
736
737fn eat(val: &Value) {}
738
739fn 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
748Or:
749
750```
751struct Value {}
752
753fn eat(val: Value) {}
754
755fn 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
764Or:
765
766```
767#[derive(Clone, Copy)] // implement Copy trait
768struct Value {}
769
770fn eat(val: Value) {}
771
772fn 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
781You can find more information about borrowing in the rust-book:
041b39d2 782http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
5bcae85e
SL
783"##,
784
a7813a04
XL
785E0506: r##"
786This error occurs when an attempt is made to assign to a borrowed value.
787
788Example of erroneous code:
789
5bcae85e 790```compile_fail,E0506
a7813a04 791struct FancyNum {
5bcae85e 792 num: u8,
a7813a04
XL
793}
794
795fn 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
805Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't
806be assigned to a new value as it would invalidate the reference.
807
808Alternatively, we can move out of `fancy_num` into a second `fancy_num`:
809
810```
811struct FancyNum {
5bcae85e 812 num: u8,
a7813a04
XL
813}
814
815fn 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
824If the value has to be borrowed, try limiting the lifetime of the borrow using
825a scoped block:
826
827```
828struct FancyNum {
5bcae85e 829 num: u8,
a7813a04
XL
830}
831
832fn 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
846Or by moving the reference into a function:
847
848```
849struct FancyNum {
5bcae85e 850 num: u8,
a7813a04
XL
851}
852
853fn 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
863fn print_fancy_ref(fancy_ref: &FancyNum){
864 println!("Ref: {}", fancy_ref.num);
865}
866```
867"##,
868
9cc50fc6
SL
869E0507: r##"
870You tried to move out of a value which was borrowed. Erroneous code example:
871
5bcae85e 872```compile_fail,E0507
9cc50fc6
SL
873use std::cell::RefCell;
874
875struct TheDarkKnight;
876
877impl TheDarkKnight {
878 fn nothing_is_true(self) {}
879}
880
881fn main() {
882 let x = RefCell::new(TheDarkKnight);
883
884 x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
885}
886```
887
888Here, the `nothing_is_true` method takes the ownership of `self`. However,
889`self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
890which is a borrow of the content owned by the `RefCell`. To fix this error,
891you 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
897Examples:
898
899```
900use std::cell::RefCell;
901
902struct TheDarkKnight;
903
904impl TheDarkKnight {
905 fn nothing_is_true(&self) {} // First case, we don't take ownership
906}
907
908fn main() {
909 let x = RefCell::new(TheDarkKnight);
910
911 x.borrow().nothing_is_true(); // ok!
912}
913```
914
915Or:
916
917```
918use std::cell::RefCell;
919
920struct TheDarkKnight;
921
922impl TheDarkKnight {
923 fn nothing_is_true(self) {}
924}
925
926fn 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
934Or:
935
936```
937use std::cell::RefCell;
938
939#[derive(Clone, Copy)] // we implement the Copy trait
940struct TheDarkKnight;
941
942impl TheDarkKnight {
943 fn nothing_is_true(self) {}
944}
945
946fn main() {
947 let x = RefCell::new(TheDarkKnight);
948
949 x.borrow().nothing_is_true(); // ok!
950}
951```
952
041b39d2 953Moving a member out of a mutably borrowed struct will also cause E0507 error:
7453a54e 954
041b39d2 955```compile_fail,E0507
7453a54e
SL
956struct TheDarkKnight;
957
958impl TheDarkKnight {
959 fn nothing_is_true(self) {}
960}
961
962struct Batcave {
963 knight: TheDarkKnight
964}
965
966fn 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
976It 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 }
982use std::mem;
983
984let mut cave = Batcave {
985 knight: TheDarkKnight
986};
987let borrowed = &mut cave;
988
989mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok!
990```
991
9cc50fc6 992You can find more information about borrowing in the rust-book:
041b39d2 993http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
9cc50fc6
SL
994"##,
995
3157f602
XL
996E0508: r##"
997A value was moved out of a non-copy fixed-size array.
998
999Example of erroneous code:
1000
5bcae85e 1001```compile_fail,E0508
3157f602
XL
1002struct NonCopy;
1003
1004fn 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
1011The first element was moved out of the array, but this is not
1012possible because `NonCopy` does not implement the `Copy` trait.
1013
1014Consider borrowing the element instead of moving it:
1015
1016```
1017struct NonCopy;
1018
1019fn main() {
1020 let array = [NonCopy; 1];
1021 let _value = &array[0]; // Borrowing is allowed, unlike moving.
1022}
1023```
1024
1025Alternatively, if your type implements `Clone` and you need to own the value,
1026consider borrowing and then cloning:
1027
1028```
1029#[derive(Clone)]
1030struct NonCopy;
1031
1032fn 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
1040E0509: r##"
1041This error occurs when an attempt is made to move out of a value whose type
1042implements the `Drop` trait.
1043
1044Example of erroneous code:
1045
5bcae85e 1046```compile_fail,E0509
a7813a04
XL
1047struct FancyNum {
1048 num: usize
1049}
1050
1051struct DropStruct {
1052 fancy: FancyNum
1053}
1054
1055impl Drop for DropStruct {
1056 fn drop(&mut self) {
1057 // Destruct DropStruct, possibly using FancyNum
1058 }
1059}
1060
1061fn 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
1069Here, we tried to move a field out of a struct of type `DropStruct` which
1070implements the `Drop` trait. However, a struct cannot be dropped if one or
1071more of its fields have been moved.
1072
1073Structs implementing the `Drop` trait have an implicit destructor that gets
1074called when they go out of scope. This destructor may use the fields of the
1075struct, so moving out of the struct could make it impossible to run the
1076destructor. Therefore, we must think of all values whose type implements the
1077`Drop` trait as single units whose fields cannot be moved.
1078
1079This error can be fixed by creating a reference to the fields of a struct,
1080enum, or tuple using the `ref` keyword:
1081
1082```
1083struct FancyNum {
1084 num: usize
1085}
1086
1087struct DropStruct {
1088 fancy: FancyNum
1089}
1090
1091impl Drop for DropStruct {
1092 fn drop(&mut self) {
1093 // Destruct DropStruct, possibly using FancyNum
1094 }
1095}
1096
1097fn 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
1105Note that this technique can also be used in the arms of a match expression:
1106
1107```
1108struct FancyNum {
1109 num: usize
1110}
1111
1112enum DropEnum {
1113 Fancy(FancyNum)
1114}
1115
1116impl Drop for DropEnum {
1117 fn drop(&mut self) {
1118 // Destruct DropEnum, possibly using FancyNum
1119 }
1120}
1121
1122fn 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
1135E0596: r##"
1136This error occurs because you tried to mutably borrow a non-mutable variable.
1137
1138Example of erroneous code:
1139
1140```compile_fail,E0596
1141let x = 1;
1142let y = &mut x; // error: cannot borrow mutably
1143```
1144
1145In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it
1146fails. To fix this error, you need to make `x` mutable:
1147
1148```
1149let mut x = 1;
1150let y = &mut x; // ok!
1151```
1152"##,
1153
1154E0597: r##"
1155This error occurs because a borrow was made inside a variable which has a
1156greater lifetime than the borrowed one.
1157
1158Example of erroneous code:
1159
1160```compile_fail,E0597
1161struct Foo<'a> {
1162 x: Option<&'a u32>,
1163}
1164
1165let mut x = Foo { x: None };
1166let y = 0;
1167x.x = Some(&y); // error: `y` does not live long enough
1168```
1169
1170In here, `x` is created before `y` and therefore has a greater lifetime. Always
1171keep in mind that values in a scope are dropped in the opposite order they are
1172created. So to fix the previous example, just make the `y` lifetime greater than
1173the `x`'s one:
1174
1175```
1176struct Foo<'a> {
1177 x: Option<&'a u32>,
1178}
1179
1180let y = 0;
1181let mut x = Foo { x: None };
1182x.x = Some(&y);
1183```
1184"##,
1185
62682a34
SL
1186}
1187
9346a6ac 1188register_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}