]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/diagnostics.rs
New upstream version 1.22.1+dfsg1
[rustc.git] / src / librustc_mir / diagnostics.rs
CommitLineData
a7813a04
XL
1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
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
11#![allow(non_snake_case)]
12
13register_long_diagnostics! {
14
15E0010: r##"
16The value of statics and constants must be known at compile time, and they live
17for the entire lifetime of a program. Creating a boxed value allocates memory on
18the heap at runtime, and therefore cannot be done at compile time. Erroneous
19code example:
20
9e0c209e 21```compile_fail,E0010
a7813a04
XL
22#![feature(box_syntax)]
23
24const CON : Box<i32> = box 0;
25```
26"##,
27
28E0013: r##"
29Static and const variables can refer to other const variables. But a const
30variable cannot refer to a static variable. For example, `Y` cannot refer to
31`X` here:
32
9e0c209e 33```compile_fail,E0013
a7813a04
XL
34static X: i32 = 42;
35const Y: i32 = X;
36```
37
38To fix this, the value can be extracted as a const and then used:
39
40```
41const A: i32 = 42;
42static X: i32 = A;
43const Y: i32 = A;
44```
45"##,
46
47// FIXME(#24111) Change the language here when const fn stabilizes
48E0015: r##"
49The only functions that can be called in static or constant expressions are
50`const` functions, and struct/enum constructors. `const` functions are only
51available on a nightly compiler. Rust currently does not support more general
52compile-time function execution.
53
54```
55const FOO: Option<u8> = Some(1); // enum constructor
56struct Bar {x: u8}
57const BAR: Bar = Bar {x: 1}; // struct constructor
58```
59
60See [RFC 911] for more details on the design of `const fn`s.
61
62[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
63"##,
64
65E0016: r##"
66Blocks in constants may only contain items (such as constant, function
67definition, etc...) and a tail expression. Erroneous code example:
68
9e0c209e 69```compile_fail,E0016
a7813a04
XL
70const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
71```
72
73To avoid it, you have to replace the non-item object:
74
75```
76const FOO: i32 = { const X : i32 = 0; X };
77```
78"##,
79
80E0017: r##"
81References in statics and constants may only refer to immutable values.
82Erroneous code example:
83
9e0c209e 84```compile_fail,E0017
a7813a04
XL
85static X: i32 = 1;
86const C: i32 = 2;
87
88// these three are not allowed:
89const CR: &'static mut i32 = &mut C;
90static STATIC_REF: &'static mut i32 = &mut X;
91static CONST_REF: &'static mut i32 = &mut C;
92```
93
94Statics are shared everywhere, and if they refer to mutable data one might
95violate memory safety since holding multiple mutable references to shared data
96is not allowed.
97
98If you really want global mutable state, try using `static mut` or a global
99`UnsafeCell`.
100"##,
101
102E0018: r##"
103
104The value of static and constant integers must be known at compile time. You
105can't cast a pointer to an integer because the address of a pointer can
106vary.
107
108For example, if you write:
109
9e0c209e 110```compile_fail,E0018
a7813a04
XL
111static MY_STATIC: u32 = 42;
112static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
113static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
114```
115
116Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However,
117the address can change when the program is linked, as well as change
118between different executions due to ASLR, and many linkers would
119not be able to calculate the value of `WHAT`.
120
121On the other hand, static and constant pointers can point either to
122a known numeric address or to the address of a symbol.
123
124```
3b2f2976 125static MY_STATIC: u32 = 42;
a7813a04 126static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
a7813a04
XL
127const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
128```
129
130This does not pose a problem by itself because they can't be
131accessed directly.
132"##,
133
134E0019: r##"
135A function call isn't allowed in the const's initialization expression
136because the expression's value must be known at compile-time. Erroneous code
137example:
138
139```compile_fail
140enum Test {
141 V1
142}
143
144impl Test {
145 fn test(&self) -> i32 {
146 12
147 }
148}
149
150fn main() {
151 const FOO: Test = Test::V1;
152
9e0c209e 153 const A: i32 = FOO.test(); // You can't call Test::func() here!
a7813a04
XL
154}
155```
156
157Remember: you can't use a function call inside a const's initialization
158expression! However, you can totally use it anywhere else:
159
160```
3b2f2976
XL
161enum Test {
162 V1
163}
164
165impl Test {
166 fn func(&self) -> i32 {
167 12
168 }
169}
170
a7813a04
XL
171fn main() {
172 const FOO: Test = Test::V1;
173
174 FOO.func(); // here is good
175 let x = FOO.func(); // or even here!
176}
177```
178"##,
179
180E0022: r##"
181Constant functions are not allowed to mutate anything. Thus, binding to an
182argument with a mutable pattern is not allowed. For example,
183
184```compile_fail
185const fn foo(mut x: u8) {
186 // do stuff
187}
188```
189
190Is incorrect because the function body may not mutate `x`.
191
192Remove any mutable bindings from the argument list to fix this error. In case
193you need to mutate the argument, try lazily initializing a global variable
194instead of using a `const fn`, or refactoring the code to a functional style to
195avoid mutation if possible.
196"##,
197
ea8adc8c
XL
198E0133: r##"
199Unsafe code was used outside of an unsafe function or block.
200
201Erroneous code example:
202
203```compile_fail,E0133
204unsafe fn f() { return; } // This is the unsafe code
205
206fn main() {
207 f(); // error: call to unsafe function requires unsafe function or block
208}
209```
210
211Using unsafe functionality is potentially dangerous and disallowed by safety
212checks. Examples:
213
214* Dereferencing raw pointers
215* Calling functions via FFI
216* Calling functions marked unsafe
217
218These safety checks can be relaxed for a section of the code by wrapping the
219unsafe instructions with an `unsafe` block. For instance:
220
221```
222unsafe fn f() { return; }
223
224fn main() {
225 unsafe { f(); } // ok!
226}
227```
228
229See also https://doc.rust-lang.org/book/first-edition/unsafe.html
230"##,
231
3b2f2976
XL
232E0381: r##"
233It is not allowed to use or capture an uninitialized variable. For example:
234
235```compile_fail,E0381
236fn main() {
237 let x: i32;
238 let y = x; // error, use of possibly uninitialized variable
239}
240```
241
242To fix this, ensure that any declared variables are initialized before being
243used. Example:
244
245```
246fn main() {
247 let x: i32 = 0;
248 let y = x; // ok!
249}
250```
251"##,
252
253E0384: r##"
254This error occurs when an attempt is made to reassign an immutable variable.
255For example:
256
257```compile_fail,E0384
258fn main() {
259 let x = 3;
260 x = 5; // error, reassignment of immutable variable
261}
262```
263
264By default, variables in Rust are immutable. To fix this error, add the keyword
265`mut` after the keyword `let` when declaring the variable. For example:
266
267```
268fn main() {
269 let mut x = 3;
270 x = 5;
271}
272```
273"##,
274
275
a7813a04 276E0394: r##"
5bcae85e 277A static was referred to by value by another static.
a7813a04 278
5bcae85e 279Erroneous code examples:
a7813a04 280
5bcae85e
SL
281```compile_fail,E0394
282static A: u32 = 0;
283static B: u32 = A; // error: cannot refer to other statics by value, use the
284 // address-of operator or a constant instead
285```
286
287A static cannot be referred by value. To fix this issue, either use a
288constant:
289
290```
291const A: u32 = 0; // `A` is now a constant
292static B: u32 = A; // ok!
293```
294
295Or refer to `A` by reference:
296
297```
298static A: u32 = 0;
299static B: &'static u32 = &A; // ok!
300```
a7813a04
XL
301"##,
302
a7813a04
XL
303E0395: r##"
304The value assigned to a constant scalar must be known at compile time,
305which is not the case when comparing raw pointers.
306
307Erroneous code example:
308
9e0c209e 309```compile_fail,E0395
a7813a04
XL
310static FOO: i32 = 42;
311static BAR: i32 = 42;
312
313static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
314// error: raw pointers cannot be compared in statics!
315```
316
317The address assigned by the linker to `FOO` and `BAR` may or may not
318be identical, so the value of `BAZ` can't be determined.
319
320If you want to do the comparison, please do it at run-time.
321
322For example:
323
324```
325static FOO: i32 = 42;
326static BAR: i32 = 42;
327
328let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
329// baz isn't a constant expression so it's ok
330```
331"##,
332
cc61c64b
XL
333E0161: r##"
334A value was moved. However, its size was not known at compile time, and only
335values of a known size can be moved.
336
337Erroneous code example:
338
339```compile_fail
340#![feature(box_syntax)]
341
342fn main() {
343 let array: &[isize] = &[1, 2, 3];
344 let _x: Box<[isize]> = box *array;
345 // error: cannot move a value of type [isize]: the size of [isize] cannot
346 // be statically determined
347}
348```
349
350In Rust, you can only move a value when its size is known at compile time.
351
352To work around this restriction, consider "hiding" the value behind a reference:
353either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
354it around as usual. Example:
355
356```
357#![feature(box_syntax)]
358
359fn main() {
360 let array: &[isize] = &[1, 2, 3];
361 let _x: Box<&[isize]> = box array; // ok!
362}
363```
364"##,
365
a7813a04
XL
366E0396: r##"
367The value behind a raw pointer can't be determined at compile-time
368(or even link-time), which means it can't be used in a constant
369expression. Erroneous code example:
370
9e0c209e 371```compile_fail,E0396
a7813a04
XL
372const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
373
374const VALUE: u8 = unsafe { *REG_ADDR };
375// error: raw pointers cannot be dereferenced in constants
376```
377
378A possible fix is to dereference your pointer at some point in run-time.
379
380For example:
381
382```
383const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
384
385let reg_value = unsafe { *REG_ADDR };
386```
387"##,
388
389E0492: r##"
390A borrow of a constant containing interior mutability was attempted. Erroneous
391code example:
392
9e0c209e 393```compile_fail,E0492
a7813a04
XL
394use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
395
396const A: AtomicUsize = ATOMIC_USIZE_INIT;
397static B: &'static AtomicUsize = &A;
041b39d2
XL
398// error: cannot borrow a constant which may contain interior mutability,
399// create a static instead
a7813a04
XL
400```
401
402A `const` represents a constant value that should never change. If one takes
403a `&` reference to the constant, then one is taking a pointer to some memory
404location containing the value. Normally this is perfectly fine: most values
405can't be changed via a shared `&` pointer, but interior mutability would allow
406it. That is, a constant value could be mutated. On the other hand, a `static` is
407explicitly a single memory location, which can be mutated at will.
408
409So, in order to solve this error, either use statics which are `Sync`:
410
411```
412use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
413
414static A: AtomicUsize = ATOMIC_USIZE_INIT;
415static B: &'static AtomicUsize = &A; // ok!
416```
417
418You can also have this error while using a cell type:
419
9e0c209e 420```compile_fail,E0492
ea8adc8c 421#![feature(const_cell_new)]
a7813a04
XL
422
423use std::cell::Cell;
424
425const A: Cell<usize> = Cell::new(1);
426const B: &'static Cell<usize> = &A;
041b39d2
XL
427// error: cannot borrow a constant which may contain interior mutability,
428// create a static instead
a7813a04
XL
429
430// or:
431struct C { a: Cell<usize> }
432
433const D: C = C { a: Cell::new(1) };
434const E: &'static Cell<usize> = &D.a; // error
435
436// or:
437const F: &'static C = &D; // error
438```
439
440This is because cell types do operations that are not thread-safe. Due to this,
441they don't implement Sync and thus can't be placed in statics. In this
442case, `StaticMutex` would work just fine, but it isn't stable yet:
443https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
444
445However, if you still wish to use these types, you can achieve this by an unsafe
446wrapper:
447
448```
ea8adc8c 449#![feature(const_cell_new)]
a7813a04
XL
450
451use std::cell::Cell;
452use std::marker::Sync;
453
454struct NotThreadSafe<T> {
455 value: Cell<T>,
456}
457
458unsafe impl<T> Sync for NotThreadSafe<T> {}
459
460static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
461static B: &'static NotThreadSafe<usize> = &A; // ok!
462```
463
464Remember this solution is unsafe! You will have to ensure that accesses to the
465cell are synchronized.
466"##,
467
a7813a04
XL
468E0494: r##"
469A reference of an interior static was assigned to another const/static.
470Erroneous code example:
471
9e0c209e 472```compile_fail,E0494
a7813a04
XL
473struct Foo {
474 a: u32
475}
476
477static S : Foo = Foo { a : 0 };
478static A : &'static u32 = &S.a;
479// error: cannot refer to the interior of another static, use a
480// constant instead
481```
482
483The "base" variable has to be a const if you want another static/const variable
484to refer to one of its fields. Example:
485
486```
487struct Foo {
488 a: u32
489}
490
491const S : Foo = Foo { a : 0 };
492static A : &'static u32 = &S.a; // ok!
493```
494"##,
495
3b2f2976
XL
496E0499: r##"
497A variable was borrowed as mutable more than once. Erroneous code example:
498
499```compile_fail,E0499
500let mut i = 0;
501let mut x = &mut i;
502let mut a = &mut i;
503// error: cannot borrow `i` as mutable more than once at a time
504```
505
506Please note that in rust, you can either have many immutable references, or one
507mutable reference. Take a look at
508https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more
509information. Example:
510
511
512```
513let mut i = 0;
514let mut x = &mut i; // ok!
515
516// or:
517let mut i = 0;
518let a = &i; // ok!
519let b = &i; // still ok!
520let c = &i; // still ok!
521```
522"##,
523
524E0500: r##"
525A borrowed variable was used in another closure. Example of erroneous code:
526
527```compile_fail
528fn you_know_nothing(jon_snow: &mut i32) {
529 let nights_watch = || {
530 *jon_snow = 2;
531 };
532 let starks = || {
533 *jon_snow = 3; // error: closure requires unique access to `jon_snow`
534 // but it is already borrowed
535 };
536}
537```
538
539In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it
540cannot be borrowed by the `starks` closure at the same time. To fix this issue,
541you can put the closure in its own scope:
542
543```
544fn you_know_nothing(jon_snow: &mut i32) {
545 {
546 let nights_watch = || {
547 *jon_snow = 2;
548 };
549 } // At this point, `jon_snow` is free.
550 let starks = || {
551 *jon_snow = 3;
552 };
553}
554```
555
556Or, if the type implements the `Clone` trait, you can clone it between
557closures:
558
559```
560fn you_know_nothing(jon_snow: &mut i32) {
561 let mut jon_copy = jon_snow.clone();
562 let nights_watch = || {
563 jon_copy = 2;
564 };
565 let starks = || {
566 *jon_snow = 3;
567 };
568}
569```
570"##,
571
572E0501: r##"
573This error indicates that a mutable variable is being used while it is still
574captured by a closure. Because the closure has borrowed the variable, it is not
575available for use until the closure goes out of scope.
576
577Note that a capture will either move or borrow a variable, but in this
578situation, the closure is borrowing the variable. Take a look at
579http://rustbyexample.com/fn/closures/capture.html for more information about
580capturing.
581
582Example of erroneous code:
583
584```compile_fail,E0501
585fn inside_closure(x: &mut i32) {
586 // Actions which require unique access
587}
588
589fn outside_closure(x: &mut i32) {
590 // Actions which require unique access
591}
592
593fn foo(a: &mut i32) {
594 let bar = || {
595 inside_closure(a)
596 };
597 outside_closure(a); // error: cannot borrow `*a` as mutable because previous
598 // closure requires unique access.
599}
600```
601
602To fix this error, you can place the closure in its own scope:
603
604```
605fn inside_closure(x: &mut i32) {}
606fn outside_closure(x: &mut i32) {}
607
608fn foo(a: &mut i32) {
609 {
610 let bar = || {
611 inside_closure(a)
612 };
613 } // borrow on `a` ends.
614 outside_closure(a); // ok!
615}
616```
617
618Or you can pass the variable as a parameter to the closure:
619
620```
621fn inside_closure(x: &mut i32) {}
622fn outside_closure(x: &mut i32) {}
623
624fn foo(a: &mut i32) {
625 let bar = |s: &mut i32| {
626 inside_closure(s)
627 };
628 outside_closure(a);
629 bar(a);
630}
631```
632
633It may be possible to define the closure later:
634
635```
636fn inside_closure(x: &mut i32) {}
637fn outside_closure(x: &mut i32) {}
638
639fn foo(a: &mut i32) {
640 outside_closure(a);
641 let bar = || {
642 inside_closure(a)
643 };
644}
645```
646"##,
647
648E0502: r##"
649This error indicates that you are trying to borrow a variable as mutable when it
650has already been borrowed as immutable.
651
652Example of erroneous code:
653
654```compile_fail,E0502
655fn bar(x: &mut i32) {}
656fn foo(a: &mut i32) {
657 let ref y = a; // a is borrowed as immutable.
658 bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed
659 // as immutable
660}
661```
662
663To fix this error, ensure that you don't have any other references to the
664variable before trying to access it mutably:
665
666```
667fn bar(x: &mut i32) {}
668fn foo(a: &mut i32) {
669 bar(a);
670 let ref y = a; // ok!
671}
672```
673
674For more information on the rust ownership system, take a look at
675https://doc.rust-lang.org/stable/book/references-and-borrowing.html.
676"##,
677
678E0503: r##"
679A value was used after it was mutably borrowed.
680
681Example of erroneous code:
682
683```compile_fail,E0503
684fn main() {
685 let mut value = 3;
686 // Create a mutable borrow of `value`. This borrow
687 // lives until the end of this function.
688 let _borrow = &mut value;
689 let _sum = value + 1; // error: cannot use `value` because
690 // it was mutably borrowed
691}
692```
693
694In this example, `value` is mutably borrowed by `borrow` and cannot be
695used to calculate `sum`. This is not possible because this would violate
696Rust's mutability rules.
697
698You can fix this error by limiting the scope of the borrow:
699
700```
701fn main() {
702 let mut value = 3;
703 // By creating a new block, you can limit the scope
704 // of the reference.
705 {
706 let _borrow = &mut value; // Use `_borrow` inside this block.
707 }
708 // The block has ended and with it the borrow.
709 // You can now use `value` again.
710 let _sum = value + 1;
711}
712```
713
714Or by cloning `value` before borrowing it:
715
716```
717fn main() {
718 let mut value = 3;
719 // We clone `value`, creating a copy.
720 let value_cloned = value.clone();
721 // The mutable borrow is a reference to `value` and
722 // not to `value_cloned`...
723 let _borrow = &mut value;
724 // ... which means we can still use `value_cloned`,
725 let _sum = value_cloned + 1;
726 // even though the borrow only ends here.
727}
728```
729
730You can find more information about borrowing in the rust-book:
731http://doc.rust-lang.org/stable/book/references-and-borrowing.html
732"##,
733
734E0504: r##"
735This error occurs when an attempt is made to move a borrowed variable into a
736closure.
737
738Example of erroneous code:
739
740```compile_fail,E0504
741struct FancyNum {
742 num: u8,
743}
744
745fn main() {
746 let fancy_num = FancyNum { num: 5 };
747 let fancy_ref = &fancy_num;
748
749 let x = move || {
750 println!("child function: {}", fancy_num.num);
751 // error: cannot move `fancy_num` into closure because it is borrowed
752 };
753
754 x();
755 println!("main function: {}", fancy_ref.num);
756}
757```
758
759Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into
760the closure `x`. There is no way to move a value into a closure while it is
761borrowed, as that would invalidate the borrow.
762
763If the closure can't outlive the value being moved, try using a reference
764rather than moving:
765
766```
767struct FancyNum {
768 num: u8,
769}
770
771fn main() {
772 let fancy_num = FancyNum { num: 5 };
773 let fancy_ref = &fancy_num;
774
775 let x = move || {
776 // fancy_ref is usable here because it doesn't move `fancy_num`
777 println!("child function: {}", fancy_ref.num);
778 };
779
780 x();
781
782 println!("main function: {}", fancy_num.num);
783}
784```
785
786If the value has to be borrowed and then moved, try limiting the lifetime of
787the borrow using a scoped block:
788
789```
790struct FancyNum {
791 num: u8,
792}
793
794fn main() {
795 let fancy_num = FancyNum { num: 5 };
796
797 {
798 let fancy_ref = &fancy_num;
799 println!("main function: {}", fancy_ref.num);
800 // `fancy_ref` goes out of scope here
801 }
802
803 let x = move || {
804 // `fancy_num` can be moved now (no more references exist)
805 println!("child function: {}", fancy_num.num);
806 };
807
808 x();
809}
810```
811
812If the lifetime of a reference isn't enough, such as in the case of threading,
813consider using an `Arc` to create a reference-counted value:
814
815```
816use std::sync::Arc;
817use std::thread;
818
819struct FancyNum {
820 num: u8,
821}
822
823fn main() {
824 let fancy_ref1 = Arc::new(FancyNum { num: 5 });
825 let fancy_ref2 = fancy_ref1.clone();
826
827 let x = thread::spawn(move || {
828 // `fancy_ref1` can be moved and has a `'static` lifetime
829 println!("child thread: {}", fancy_ref1.num);
830 });
831
832 x.join().expect("child thread should finish");
833 println!("main thread: {}", fancy_ref2.num);
834}
835```
836"##,
837
838E0505: r##"
839A value was moved out while it was still borrowed.
840
841Erroneous code example:
842
843```compile_fail,E0505
844struct Value {}
845
846fn eat(val: Value) {}
847
848fn main() {
849 let x = Value{};
850 {
851 let _ref_to_val: &Value = &x;
852 eat(x);
853 }
854}
855```
856
857Here, the function `eat` takes the ownership of `x`. However,
858`x` cannot be moved because it was borrowed to `_ref_to_val`.
859To fix that you can do few different things:
860
861* Try to avoid moving the variable.
862* Release borrow before move.
863* Implement the `Copy` trait on the type.
864
865Examples:
866
867```
868struct Value {}
869
870fn eat(val: &Value) {}
871
872fn main() {
873 let x = Value{};
874 {
875 let _ref_to_val: &Value = &x;
876 eat(&x); // pass by reference, if it's possible
877 }
878}
879```
880
881Or:
882
883```
884struct Value {}
885
886fn eat(val: Value) {}
887
888fn main() {
889 let x = Value{};
890 {
891 let _ref_to_val: &Value = &x;
892 }
893 eat(x); // release borrow and then move it.
894}
895```
896
897Or:
898
899```
900#[derive(Clone, Copy)] // implement Copy trait
901struct Value {}
902
903fn eat(val: Value) {}
904
905fn main() {
906 let x = Value{};
907 {
908 let _ref_to_val: &Value = &x;
909 eat(x); // it will be copied here.
910 }
911}
912```
913
914You can find more information about borrowing in the rust-book:
915http://doc.rust-lang.org/stable/book/references-and-borrowing.html
916"##,
917
918E0506: r##"
919This error occurs when an attempt is made to assign to a borrowed value.
920
921Example of erroneous code:
922
923```compile_fail,E0506
924struct FancyNum {
925 num: u8,
926}
927
928fn main() {
929 let mut fancy_num = FancyNum { num: 5 };
930 let fancy_ref = &fancy_num;
931 fancy_num = FancyNum { num: 6 };
932 // error: cannot assign to `fancy_num` because it is borrowed
933
934 println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
935}
936```
937
938Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't
939be assigned to a new value as it would invalidate the reference.
940
941Alternatively, we can move out of `fancy_num` into a second `fancy_num`:
942
943```
944struct FancyNum {
945 num: u8,
946}
947
948fn main() {
949 let mut fancy_num = FancyNum { num: 5 };
950 let moved_num = fancy_num;
951 fancy_num = FancyNum { num: 6 };
952
953 println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num);
954}
955```
956
957If the value has to be borrowed, try limiting the lifetime of the borrow using
958a scoped block:
959
960```
961struct FancyNum {
962 num: u8,
963}
964
965fn main() {
966 let mut fancy_num = FancyNum { num: 5 };
967
968 {
969 let fancy_ref = &fancy_num;
970 println!("Ref: {}", fancy_ref.num);
971 }
972
973 // Works because `fancy_ref` is no longer in scope
974 fancy_num = FancyNum { num: 6 };
975 println!("Num: {}", fancy_num.num);
976}
977```
978
979Or by moving the reference into a function:
980
981```
982struct FancyNum {
983 num: u8,
984}
985
986fn main() {
987 let mut fancy_num = FancyNum { num: 5 };
988
989 print_fancy_ref(&fancy_num);
990
991 // Works because function borrow has ended
992 fancy_num = FancyNum { num: 6 };
993 println!("Num: {}", fancy_num.num);
994}
995
996fn print_fancy_ref(fancy_ref: &FancyNum){
997 println!("Ref: {}", fancy_ref.num);
998}
999```
1000"##,
1001
ea8adc8c
XL
1002E0507: r##"
1003You tried to move out of a value which was borrowed. Erroneous code example:
1004
1005```compile_fail,E0507
1006use std::cell::RefCell;
1007
1008struct TheDarkKnight;
1009
1010impl TheDarkKnight {
1011 fn nothing_is_true(self) {}
1012}
1013
1014fn main() {
1015 let x = RefCell::new(TheDarkKnight);
1016
1017 x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
1018}
1019```
1020
1021Here, the `nothing_is_true` method takes the ownership of `self`. However,
1022`self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
1023which is a borrow of the content owned by the `RefCell`. To fix this error,
1024you have three choices:
1025
1026* Try to avoid moving the variable.
1027* Somehow reclaim the ownership.
1028* Implement the `Copy` trait on the type.
1029
1030Examples:
1031
1032```
1033use std::cell::RefCell;
1034
1035struct TheDarkKnight;
1036
1037impl TheDarkKnight {
1038 fn nothing_is_true(&self) {} // First case, we don't take ownership
1039}
1040
1041fn main() {
1042 let x = RefCell::new(TheDarkKnight);
1043
1044 x.borrow().nothing_is_true(); // ok!
1045}
1046```
1047
1048Or:
1049
1050```
1051use std::cell::RefCell;
1052
1053struct TheDarkKnight;
1054
1055impl TheDarkKnight {
1056 fn nothing_is_true(self) {}
1057}
1058
1059fn main() {
1060 let x = RefCell::new(TheDarkKnight);
1061 let x = x.into_inner(); // we get back ownership
1062
1063 x.nothing_is_true(); // ok!
1064}
1065```
1066
1067Or:
1068
1069```
1070use std::cell::RefCell;
1071
1072#[derive(Clone, Copy)] // we implement the Copy trait
1073struct TheDarkKnight;
1074
1075impl TheDarkKnight {
1076 fn nothing_is_true(self) {}
1077}
1078
1079fn main() {
1080 let x = RefCell::new(TheDarkKnight);
1081
1082 x.borrow().nothing_is_true(); // ok!
1083}
1084```
1085
1086Moving a member out of a mutably borrowed struct will also cause E0507 error:
1087
1088```compile_fail,E0507
1089struct TheDarkKnight;
1090
1091impl TheDarkKnight {
1092 fn nothing_is_true(self) {}
1093}
1094
1095struct Batcave {
1096 knight: TheDarkKnight
1097}
1098
1099fn main() {
1100 let mut cave = Batcave {
1101 knight: TheDarkKnight
1102 };
1103 let borrowed = &mut cave;
1104
1105 borrowed.knight.nothing_is_true(); // E0507
1106}
1107```
1108
1109It is fine only if you put something back. `mem::replace` can be used for that:
1110
1111```
1112# struct TheDarkKnight;
1113# impl TheDarkKnight { fn nothing_is_true(self) {} }
1114# struct Batcave { knight: TheDarkKnight }
1115use std::mem;
1116
1117let mut cave = Batcave {
1118 knight: TheDarkKnight
1119};
1120let borrowed = &mut cave;
1121
1122mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok!
1123```
1124
1125You can find more information about borrowing in the rust-book:
1126http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
1127"##,
1128
1129E0508: r##"
1130A value was moved out of a non-copy fixed-size array.
1131
1132Example of erroneous code:
1133
1134```compile_fail,E0508
1135struct NonCopy;
1136
1137fn main() {
1138 let array = [NonCopy; 1];
1139 let _value = array[0]; // error: cannot move out of type `[NonCopy; 1]`,
1140 // a non-copy fixed-size array
1141}
1142```
1143
1144The first element was moved out of the array, but this is not
1145possible because `NonCopy` does not implement the `Copy` trait.
1146
1147Consider borrowing the element instead of moving it:
1148
1149```
1150struct NonCopy;
1151
1152fn main() {
1153 let array = [NonCopy; 1];
1154 let _value = &array[0]; // Borrowing is allowed, unlike moving.
1155}
1156```
1157
1158Alternatively, if your type implements `Clone` and you need to own the value,
1159consider borrowing and then cloning:
1160
1161```
1162#[derive(Clone)]
1163struct NonCopy;
1164
1165fn main() {
1166 let array = [NonCopy; 1];
1167 // Now you can clone the array element.
1168 let _value = array[0].clone();
1169}
1170```
1171"##,
1172
1173E0509: r##"
1174This error occurs when an attempt is made to move out of a value whose type
1175implements the `Drop` trait.
1176
1177Example of erroneous code:
1178
1179```compile_fail,E0509
1180struct FancyNum {
1181 num: usize
1182}
1183
1184struct DropStruct {
1185 fancy: FancyNum
1186}
1187
1188impl Drop for DropStruct {
1189 fn drop(&mut self) {
1190 // Destruct DropStruct, possibly using FancyNum
1191 }
1192}
1193
1194fn main() {
1195 let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
1196 let fancy_field = drop_struct.fancy; // Error E0509
1197 println!("Fancy: {}", fancy_field.num);
1198 // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
1199}
1200```
1201
1202Here, we tried to move a field out of a struct of type `DropStruct` which
1203implements the `Drop` trait. However, a struct cannot be dropped if one or
1204more of its fields have been moved.
1205
1206Structs implementing the `Drop` trait have an implicit destructor that gets
1207called when they go out of scope. This destructor may use the fields of the
1208struct, so moving out of the struct could make it impossible to run the
1209destructor. Therefore, we must think of all values whose type implements the
1210`Drop` trait as single units whose fields cannot be moved.
1211
1212This error can be fixed by creating a reference to the fields of a struct,
1213enum, or tuple using the `ref` keyword:
1214
1215```
1216struct FancyNum {
1217 num: usize
1218}
1219
1220struct DropStruct {
1221 fancy: FancyNum
1222}
1223
1224impl Drop for DropStruct {
1225 fn drop(&mut self) {
1226 // Destruct DropStruct, possibly using FancyNum
1227 }
1228}
1229
1230fn main() {
1231 let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
1232 let ref fancy_field = drop_struct.fancy; // No more errors!
1233 println!("Fancy: {}", fancy_field.num);
1234 // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
1235}
1236```
1237
1238Note that this technique can also be used in the arms of a match expression:
1239
1240```
1241struct FancyNum {
1242 num: usize
1243}
1244
1245enum DropEnum {
1246 Fancy(FancyNum)
1247}
1248
1249impl Drop for DropEnum {
1250 fn drop(&mut self) {
1251 // Destruct DropEnum, possibly using FancyNum
1252 }
1253}
1254
1255fn main() {
1256 // Creates and enum of type `DropEnum`, which implements `Drop`
1257 let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
1258 match drop_enum {
1259 // Creates a reference to the inside of `DropEnum::Fancy`
1260 DropEnum::Fancy(ref fancy_field) => // No error!
1261 println!("It was fancy-- {}!", fancy_field.num),
1262 }
1263 // implicit call to `drop_enum.drop()` as drop_enum goes out of scope
1264}
1265```
1266"##,
1267
a7813a04
XL
1268}
1269
1270register_diagnostics! {
ea8adc8c 1271 E0493, // destructors cannot be evaluated at compile-time
3b2f2976 1272 E0524, // two closures require unique access to `..` at the same time
a7813a04 1273 E0526, // shuffle indices are not constant
ea8adc8c 1274 E0594, // cannot assign to {}
3b2f2976 1275 E0625, // thread-local statics cannot be accessed at compile-time
a7813a04 1276}