]>
Commit | Line | Data |
---|---|---|
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 | ||
13 | register_long_diagnostics! { | |
14 | ||
15 | E0010: r##" | |
16 | The value of statics and constants must be known at compile time, and they live | |
17 | for the entire lifetime of a program. Creating a boxed value allocates memory on | |
18 | the heap at runtime, and therefore cannot be done at compile time. Erroneous | |
19 | code example: | |
20 | ||
9e0c209e | 21 | ```compile_fail,E0010 |
a7813a04 XL |
22 | #![feature(box_syntax)] |
23 | ||
24 | const CON : Box<i32> = box 0; | |
25 | ``` | |
26 | "##, | |
27 | ||
28 | E0013: r##" | |
29 | Static and const variables can refer to other const variables. But a const | |
30 | variable cannot refer to a static variable. For example, `Y` cannot refer to | |
31 | `X` here: | |
32 | ||
9e0c209e | 33 | ```compile_fail,E0013 |
a7813a04 XL |
34 | static X: i32 = 42; |
35 | const Y: i32 = X; | |
36 | ``` | |
37 | ||
38 | To fix this, the value can be extracted as a const and then used: | |
39 | ||
40 | ``` | |
41 | const A: i32 = 42; | |
42 | static X: i32 = A; | |
43 | const Y: i32 = A; | |
44 | ``` | |
45 | "##, | |
46 | ||
47 | // FIXME(#24111) Change the language here when const fn stabilizes | |
48 | E0015: r##" | |
49 | The only functions that can be called in static or constant expressions are | |
50 | `const` functions, and struct/enum constructors. `const` functions are only | |
51 | available on a nightly compiler. Rust currently does not support more general | |
52 | compile-time function execution. | |
53 | ||
54 | ``` | |
55 | const FOO: Option<u8> = Some(1); // enum constructor | |
56 | struct Bar {x: u8} | |
57 | const BAR: Bar = Bar {x: 1}; // struct constructor | |
58 | ``` | |
59 | ||
60 | See [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 | ||
65 | E0016: r##" | |
66 | Blocks in constants may only contain items (such as constant, function | |
67 | definition, etc...) and a tail expression. Erroneous code example: | |
68 | ||
9e0c209e | 69 | ```compile_fail,E0016 |
a7813a04 XL |
70 | const FOO: i32 = { let x = 0; x }; // 'x' isn't an item! |
71 | ``` | |
72 | ||
73 | To avoid it, you have to replace the non-item object: | |
74 | ||
75 | ``` | |
76 | const FOO: i32 = { const X : i32 = 0; X }; | |
77 | ``` | |
78 | "##, | |
79 | ||
80 | E0017: r##" | |
81 | References in statics and constants may only refer to immutable values. | |
82 | Erroneous code example: | |
83 | ||
9e0c209e | 84 | ```compile_fail,E0017 |
a7813a04 XL |
85 | static X: i32 = 1; |
86 | const C: i32 = 2; | |
87 | ||
88 | // these three are not allowed: | |
89 | const CR: &'static mut i32 = &mut C; | |
90 | static STATIC_REF: &'static mut i32 = &mut X; | |
91 | static CONST_REF: &'static mut i32 = &mut C; | |
92 | ``` | |
93 | ||
94 | Statics are shared everywhere, and if they refer to mutable data one might | |
95 | violate memory safety since holding multiple mutable references to shared data | |
96 | is not allowed. | |
97 | ||
98 | If you really want global mutable state, try using `static mut` or a global | |
99 | `UnsafeCell`. | |
100 | "##, | |
101 | ||
102 | E0018: r##" | |
103 | ||
104 | The value of static and constant integers must be known at compile time. You | |
105 | can't cast a pointer to an integer because the address of a pointer can | |
106 | vary. | |
107 | ||
108 | For example, if you write: | |
109 | ||
9e0c209e | 110 | ```compile_fail,E0018 |
a7813a04 XL |
111 | static MY_STATIC: u32 = 42; |
112 | static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize; | |
113 | static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR; | |
114 | ``` | |
115 | ||
116 | Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However, | |
117 | the address can change when the program is linked, as well as change | |
118 | between different executions due to ASLR, and many linkers would | |
119 | not be able to calculate the value of `WHAT`. | |
120 | ||
121 | On the other hand, static and constant pointers can point either to | |
122 | a known numeric address or to the address of a symbol. | |
123 | ||
124 | ``` | |
3b2f2976 | 125 | static MY_STATIC: u32 = 42; |
a7813a04 | 126 | static MY_STATIC_ADDR: &'static u32 = &MY_STATIC; |
a7813a04 XL |
127 | const CONST_ADDR: *const u8 = 0x5f3759df as *const u8; |
128 | ``` | |
129 | ||
130 | This does not pose a problem by itself because they can't be | |
131 | accessed directly. | |
132 | "##, | |
133 | ||
134 | E0019: r##" | |
135 | A function call isn't allowed in the const's initialization expression | |
136 | because the expression's value must be known at compile-time. Erroneous code | |
137 | example: | |
138 | ||
139 | ```compile_fail | |
140 | enum Test { | |
141 | V1 | |
142 | } | |
143 | ||
144 | impl Test { | |
145 | fn test(&self) -> i32 { | |
146 | 12 | |
147 | } | |
148 | } | |
149 | ||
150 | fn 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 | ||
157 | Remember: you can't use a function call inside a const's initialization | |
158 | expression! However, you can totally use it anywhere else: | |
159 | ||
160 | ``` | |
3b2f2976 XL |
161 | enum Test { |
162 | V1 | |
163 | } | |
164 | ||
165 | impl Test { | |
166 | fn func(&self) -> i32 { | |
167 | 12 | |
168 | } | |
169 | } | |
170 | ||
a7813a04 XL |
171 | fn 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 | ||
180 | E0022: r##" | |
181 | Constant functions are not allowed to mutate anything. Thus, binding to an | |
182 | argument with a mutable pattern is not allowed. For example, | |
183 | ||
184 | ```compile_fail | |
185 | const fn foo(mut x: u8) { | |
186 | // do stuff | |
187 | } | |
188 | ``` | |
189 | ||
190 | Is incorrect because the function body may not mutate `x`. | |
191 | ||
192 | Remove any mutable bindings from the argument list to fix this error. In case | |
193 | you need to mutate the argument, try lazily initializing a global variable | |
194 | instead of using a `const fn`, or refactoring the code to a functional style to | |
195 | avoid mutation if possible. | |
196 | "##, | |
197 | ||
ea8adc8c XL |
198 | E0133: r##" |
199 | Unsafe code was used outside of an unsafe function or block. | |
200 | ||
201 | Erroneous code example: | |
202 | ||
203 | ```compile_fail,E0133 | |
204 | unsafe fn f() { return; } // This is the unsafe code | |
205 | ||
206 | fn main() { | |
207 | f(); // error: call to unsafe function requires unsafe function or block | |
208 | } | |
209 | ``` | |
210 | ||
211 | Using unsafe functionality is potentially dangerous and disallowed by safety | |
212 | checks. Examples: | |
213 | ||
214 | * Dereferencing raw pointers | |
215 | * Calling functions via FFI | |
216 | * Calling functions marked unsafe | |
217 | ||
218 | These safety checks can be relaxed for a section of the code by wrapping the | |
219 | unsafe instructions with an `unsafe` block. For instance: | |
220 | ||
221 | ``` | |
222 | unsafe fn f() { return; } | |
223 | ||
224 | fn main() { | |
225 | unsafe { f(); } // ok! | |
226 | } | |
227 | ``` | |
228 | ||
229 | See also https://doc.rust-lang.org/book/first-edition/unsafe.html | |
230 | "##, | |
231 | ||
3b2f2976 XL |
232 | E0381: r##" |
233 | It is not allowed to use or capture an uninitialized variable. For example: | |
234 | ||
235 | ```compile_fail,E0381 | |
236 | fn main() { | |
237 | let x: i32; | |
238 | let y = x; // error, use of possibly uninitialized variable | |
239 | } | |
240 | ``` | |
241 | ||
242 | To fix this, ensure that any declared variables are initialized before being | |
243 | used. Example: | |
244 | ||
245 | ``` | |
246 | fn main() { | |
247 | let x: i32 = 0; | |
248 | let y = x; // ok! | |
249 | } | |
250 | ``` | |
251 | "##, | |
252 | ||
253 | E0384: r##" | |
254 | This error occurs when an attempt is made to reassign an immutable variable. | |
255 | For example: | |
256 | ||
257 | ```compile_fail,E0384 | |
258 | fn main() { | |
259 | let x = 3; | |
260 | x = 5; // error, reassignment of immutable variable | |
261 | } | |
262 | ``` | |
263 | ||
264 | By 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 | ``` | |
268 | fn main() { | |
269 | let mut x = 3; | |
270 | x = 5; | |
271 | } | |
272 | ``` | |
273 | "##, | |
274 | ||
275 | ||
a7813a04 | 276 | E0394: r##" |
5bcae85e | 277 | A static was referred to by value by another static. |
a7813a04 | 278 | |
5bcae85e | 279 | Erroneous code examples: |
a7813a04 | 280 | |
5bcae85e SL |
281 | ```compile_fail,E0394 |
282 | static A: u32 = 0; | |
283 | static B: u32 = A; // error: cannot refer to other statics by value, use the | |
284 | // address-of operator or a constant instead | |
285 | ``` | |
286 | ||
287 | A static cannot be referred by value. To fix this issue, either use a | |
288 | constant: | |
289 | ||
290 | ``` | |
291 | const A: u32 = 0; // `A` is now a constant | |
292 | static B: u32 = A; // ok! | |
293 | ``` | |
294 | ||
295 | Or refer to `A` by reference: | |
296 | ||
297 | ``` | |
298 | static A: u32 = 0; | |
299 | static B: &'static u32 = &A; // ok! | |
300 | ``` | |
a7813a04 XL |
301 | "##, |
302 | ||
a7813a04 XL |
303 | E0395: r##" |
304 | The value assigned to a constant scalar must be known at compile time, | |
305 | which is not the case when comparing raw pointers. | |
306 | ||
307 | Erroneous code example: | |
308 | ||
9e0c209e | 309 | ```compile_fail,E0395 |
a7813a04 XL |
310 | static FOO: i32 = 42; |
311 | static BAR: i32 = 42; | |
312 | ||
313 | static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; | |
314 | // error: raw pointers cannot be compared in statics! | |
315 | ``` | |
316 | ||
317 | The address assigned by the linker to `FOO` and `BAR` may or may not | |
318 | be identical, so the value of `BAZ` can't be determined. | |
319 | ||
320 | If you want to do the comparison, please do it at run-time. | |
321 | ||
322 | For example: | |
323 | ||
324 | ``` | |
325 | static FOO: i32 = 42; | |
326 | static BAR: i32 = 42; | |
327 | ||
328 | let 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 |
333 | E0161: r##" |
334 | A value was moved. However, its size was not known at compile time, and only | |
335 | values of a known size can be moved. | |
336 | ||
337 | Erroneous code example: | |
338 | ||
339 | ```compile_fail | |
340 | #![feature(box_syntax)] | |
341 | ||
342 | fn 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 | ||
350 | In Rust, you can only move a value when its size is known at compile time. | |
351 | ||
352 | To work around this restriction, consider "hiding" the value behind a reference: | |
353 | either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move | |
354 | it around as usual. Example: | |
355 | ||
356 | ``` | |
357 | #![feature(box_syntax)] | |
358 | ||
359 | fn main() { | |
360 | let array: &[isize] = &[1, 2, 3]; | |
361 | let _x: Box<&[isize]> = box array; // ok! | |
362 | } | |
363 | ``` | |
364 | "##, | |
365 | ||
a7813a04 XL |
366 | E0396: r##" |
367 | The 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 | |
369 | expression. Erroneous code example: | |
370 | ||
9e0c209e | 371 | ```compile_fail,E0396 |
a7813a04 XL |
372 | const REG_ADDR: *const u8 = 0x5f3759df as *const u8; |
373 | ||
374 | const VALUE: u8 = unsafe { *REG_ADDR }; | |
375 | // error: raw pointers cannot be dereferenced in constants | |
376 | ``` | |
377 | ||
378 | A possible fix is to dereference your pointer at some point in run-time. | |
379 | ||
380 | For example: | |
381 | ||
382 | ``` | |
383 | const REG_ADDR: *const u8 = 0x5f3759df as *const u8; | |
384 | ||
385 | let reg_value = unsafe { *REG_ADDR }; | |
386 | ``` | |
387 | "##, | |
388 | ||
389 | E0492: r##" | |
390 | A borrow of a constant containing interior mutability was attempted. Erroneous | |
391 | code example: | |
392 | ||
9e0c209e | 393 | ```compile_fail,E0492 |
a7813a04 XL |
394 | use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; |
395 | ||
396 | const A: AtomicUsize = ATOMIC_USIZE_INIT; | |
397 | static 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 | ||
402 | A `const` represents a constant value that should never change. If one takes | |
403 | a `&` reference to the constant, then one is taking a pointer to some memory | |
404 | location containing the value. Normally this is perfectly fine: most values | |
405 | can't be changed via a shared `&` pointer, but interior mutability would allow | |
406 | it. That is, a constant value could be mutated. On the other hand, a `static` is | |
407 | explicitly a single memory location, which can be mutated at will. | |
408 | ||
409 | So, in order to solve this error, either use statics which are `Sync`: | |
410 | ||
411 | ``` | |
412 | use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; | |
413 | ||
414 | static A: AtomicUsize = ATOMIC_USIZE_INIT; | |
415 | static B: &'static AtomicUsize = &A; // ok! | |
416 | ``` | |
417 | ||
418 | You 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 | |
423 | use std::cell::Cell; | |
424 | ||
425 | const A: Cell<usize> = Cell::new(1); | |
426 | const 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: | |
431 | struct C { a: Cell<usize> } | |
432 | ||
433 | const D: C = C { a: Cell::new(1) }; | |
434 | const E: &'static Cell<usize> = &D.a; // error | |
435 | ||
436 | // or: | |
437 | const F: &'static C = &D; // error | |
438 | ``` | |
439 | ||
440 | This is because cell types do operations that are not thread-safe. Due to this, | |
441 | they don't implement Sync and thus can't be placed in statics. In this | |
442 | case, `StaticMutex` would work just fine, but it isn't stable yet: | |
443 | https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html | |
444 | ||
445 | However, if you still wish to use these types, you can achieve this by an unsafe | |
446 | wrapper: | |
447 | ||
448 | ``` | |
ea8adc8c | 449 | #![feature(const_cell_new)] |
a7813a04 XL |
450 | |
451 | use std::cell::Cell; | |
452 | use std::marker::Sync; | |
453 | ||
454 | struct NotThreadSafe<T> { | |
455 | value: Cell<T>, | |
456 | } | |
457 | ||
458 | unsafe impl<T> Sync for NotThreadSafe<T> {} | |
459 | ||
460 | static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) }; | |
461 | static B: &'static NotThreadSafe<usize> = &A; // ok! | |
462 | ``` | |
463 | ||
464 | Remember this solution is unsafe! You will have to ensure that accesses to the | |
465 | cell are synchronized. | |
466 | "##, | |
467 | ||
a7813a04 XL |
468 | E0494: r##" |
469 | A reference of an interior static was assigned to another const/static. | |
470 | Erroneous code example: | |
471 | ||
9e0c209e | 472 | ```compile_fail,E0494 |
a7813a04 XL |
473 | struct Foo { |
474 | a: u32 | |
475 | } | |
476 | ||
477 | static S : Foo = Foo { a : 0 }; | |
478 | static A : &'static u32 = &S.a; | |
479 | // error: cannot refer to the interior of another static, use a | |
480 | // constant instead | |
481 | ``` | |
482 | ||
483 | The "base" variable has to be a const if you want another static/const variable | |
484 | to refer to one of its fields. Example: | |
485 | ||
486 | ``` | |
487 | struct Foo { | |
488 | a: u32 | |
489 | } | |
490 | ||
491 | const S : Foo = Foo { a : 0 }; | |
492 | static A : &'static u32 = &S.a; // ok! | |
493 | ``` | |
494 | "##, | |
495 | ||
3b2f2976 XL |
496 | E0499: r##" |
497 | A variable was borrowed as mutable more than once. Erroneous code example: | |
498 | ||
499 | ```compile_fail,E0499 | |
500 | let mut i = 0; | |
501 | let mut x = &mut i; | |
502 | let mut a = &mut i; | |
503 | // error: cannot borrow `i` as mutable more than once at a time | |
504 | ``` | |
505 | ||
506 | Please note that in rust, you can either have many immutable references, or one | |
507 | mutable reference. Take a look at | |
508 | https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more | |
509 | information. Example: | |
510 | ||
511 | ||
512 | ``` | |
513 | let mut i = 0; | |
514 | let mut x = &mut i; // ok! | |
515 | ||
516 | // or: | |
517 | let mut i = 0; | |
518 | let a = &i; // ok! | |
519 | let b = &i; // still ok! | |
520 | let c = &i; // still ok! | |
521 | ``` | |
522 | "##, | |
523 | ||
524 | E0500: r##" | |
525 | A borrowed variable was used in another closure. Example of erroneous code: | |
526 | ||
527 | ```compile_fail | |
528 | fn 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 | ||
539 | In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it | |
540 | cannot be borrowed by the `starks` closure at the same time. To fix this issue, | |
541 | you can put the closure in its own scope: | |
542 | ||
543 | ``` | |
544 | fn 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 | ||
556 | Or, if the type implements the `Clone` trait, you can clone it between | |
557 | closures: | |
558 | ||
559 | ``` | |
560 | fn 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 | ||
572 | E0501: r##" | |
573 | This error indicates that a mutable variable is being used while it is still | |
574 | captured by a closure. Because the closure has borrowed the variable, it is not | |
575 | available for use until the closure goes out of scope. | |
576 | ||
577 | Note that a capture will either move or borrow a variable, but in this | |
578 | situation, the closure is borrowing the variable. Take a look at | |
579 | http://rustbyexample.com/fn/closures/capture.html for more information about | |
580 | capturing. | |
581 | ||
582 | Example of erroneous code: | |
583 | ||
584 | ```compile_fail,E0501 | |
585 | fn inside_closure(x: &mut i32) { | |
586 | // Actions which require unique access | |
587 | } | |
588 | ||
589 | fn outside_closure(x: &mut i32) { | |
590 | // Actions which require unique access | |
591 | } | |
592 | ||
593 | fn 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 | ||
602 | To fix this error, you can place the closure in its own scope: | |
603 | ||
604 | ``` | |
605 | fn inside_closure(x: &mut i32) {} | |
606 | fn outside_closure(x: &mut i32) {} | |
607 | ||
608 | fn 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 | ||
618 | Or you can pass the variable as a parameter to the closure: | |
619 | ||
620 | ``` | |
621 | fn inside_closure(x: &mut i32) {} | |
622 | fn outside_closure(x: &mut i32) {} | |
623 | ||
624 | fn 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 | ||
633 | It may be possible to define the closure later: | |
634 | ||
635 | ``` | |
636 | fn inside_closure(x: &mut i32) {} | |
637 | fn outside_closure(x: &mut i32) {} | |
638 | ||
639 | fn foo(a: &mut i32) { | |
640 | outside_closure(a); | |
641 | let bar = || { | |
642 | inside_closure(a) | |
643 | }; | |
644 | } | |
645 | ``` | |
646 | "##, | |
647 | ||
648 | E0502: r##" | |
649 | This error indicates that you are trying to borrow a variable as mutable when it | |
650 | has already been borrowed as immutable. | |
651 | ||
652 | Example of erroneous code: | |
653 | ||
654 | ```compile_fail,E0502 | |
655 | fn bar(x: &mut i32) {} | |
656 | fn 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 | ||
663 | To fix this error, ensure that you don't have any other references to the | |
664 | variable before trying to access it mutably: | |
665 | ||
666 | ``` | |
667 | fn bar(x: &mut i32) {} | |
668 | fn foo(a: &mut i32) { | |
669 | bar(a); | |
670 | let ref y = a; // ok! | |
671 | } | |
672 | ``` | |
673 | ||
674 | For more information on the rust ownership system, take a look at | |
675 | https://doc.rust-lang.org/stable/book/references-and-borrowing.html. | |
676 | "##, | |
677 | ||
678 | E0503: r##" | |
679 | A value was used after it was mutably borrowed. | |
680 | ||
681 | Example of erroneous code: | |
682 | ||
683 | ```compile_fail,E0503 | |
684 | fn 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 | ||
694 | In this example, `value` is mutably borrowed by `borrow` and cannot be | |
695 | used to calculate `sum`. This is not possible because this would violate | |
696 | Rust's mutability rules. | |
697 | ||
698 | You can fix this error by limiting the scope of the borrow: | |
699 | ||
700 | ``` | |
701 | fn 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 | ||
714 | Or by cloning `value` before borrowing it: | |
715 | ||
716 | ``` | |
717 | fn 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 | ||
730 | You can find more information about borrowing in the rust-book: | |
731 | http://doc.rust-lang.org/stable/book/references-and-borrowing.html | |
732 | "##, | |
733 | ||
734 | E0504: r##" | |
735 | This error occurs when an attempt is made to move a borrowed variable into a | |
736 | closure. | |
737 | ||
738 | Example of erroneous code: | |
739 | ||
740 | ```compile_fail,E0504 | |
741 | struct FancyNum { | |
742 | num: u8, | |
743 | } | |
744 | ||
745 | fn 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 | ||
759 | Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into | |
760 | the closure `x`. There is no way to move a value into a closure while it is | |
761 | borrowed, as that would invalidate the borrow. | |
762 | ||
763 | If the closure can't outlive the value being moved, try using a reference | |
764 | rather than moving: | |
765 | ||
766 | ``` | |
767 | struct FancyNum { | |
768 | num: u8, | |
769 | } | |
770 | ||
771 | fn 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 | ||
786 | If the value has to be borrowed and then moved, try limiting the lifetime of | |
787 | the borrow using a scoped block: | |
788 | ||
789 | ``` | |
790 | struct FancyNum { | |
791 | num: u8, | |
792 | } | |
793 | ||
794 | fn 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 | ||
812 | If the lifetime of a reference isn't enough, such as in the case of threading, | |
813 | consider using an `Arc` to create a reference-counted value: | |
814 | ||
815 | ``` | |
816 | use std::sync::Arc; | |
817 | use std::thread; | |
818 | ||
819 | struct FancyNum { | |
820 | num: u8, | |
821 | } | |
822 | ||
823 | fn 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 | ||
838 | E0505: r##" | |
839 | A value was moved out while it was still borrowed. | |
840 | ||
841 | Erroneous code example: | |
842 | ||
843 | ```compile_fail,E0505 | |
844 | struct Value {} | |
845 | ||
846 | fn eat(val: Value) {} | |
847 | ||
848 | fn main() { | |
849 | let x = Value{}; | |
850 | { | |
851 | let _ref_to_val: &Value = &x; | |
852 | eat(x); | |
853 | } | |
854 | } | |
855 | ``` | |
856 | ||
857 | Here, the function `eat` takes the ownership of `x`. However, | |
858 | `x` cannot be moved because it was borrowed to `_ref_to_val`. | |
859 | To 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 | ||
865 | Examples: | |
866 | ||
867 | ``` | |
868 | struct Value {} | |
869 | ||
870 | fn eat(val: &Value) {} | |
871 | ||
872 | fn 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 | ||
881 | Or: | |
882 | ||
883 | ``` | |
884 | struct Value {} | |
885 | ||
886 | fn eat(val: Value) {} | |
887 | ||
888 | fn 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 | ||
897 | Or: | |
898 | ||
899 | ``` | |
900 | #[derive(Clone, Copy)] // implement Copy trait | |
901 | struct Value {} | |
902 | ||
903 | fn eat(val: Value) {} | |
904 | ||
905 | fn 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 | ||
914 | You can find more information about borrowing in the rust-book: | |
915 | http://doc.rust-lang.org/stable/book/references-and-borrowing.html | |
916 | "##, | |
917 | ||
918 | E0506: r##" | |
919 | This error occurs when an attempt is made to assign to a borrowed value. | |
920 | ||
921 | Example of erroneous code: | |
922 | ||
923 | ```compile_fail,E0506 | |
924 | struct FancyNum { | |
925 | num: u8, | |
926 | } | |
927 | ||
928 | fn 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 | ||
938 | Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't | |
939 | be assigned to a new value as it would invalidate the reference. | |
940 | ||
941 | Alternatively, we can move out of `fancy_num` into a second `fancy_num`: | |
942 | ||
943 | ``` | |
944 | struct FancyNum { | |
945 | num: u8, | |
946 | } | |
947 | ||
948 | fn 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 | ||
957 | If the value has to be borrowed, try limiting the lifetime of the borrow using | |
958 | a scoped block: | |
959 | ||
960 | ``` | |
961 | struct FancyNum { | |
962 | num: u8, | |
963 | } | |
964 | ||
965 | fn 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 | ||
979 | Or by moving the reference into a function: | |
980 | ||
981 | ``` | |
982 | struct FancyNum { | |
983 | num: u8, | |
984 | } | |
985 | ||
986 | fn 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 | ||
996 | fn print_fancy_ref(fancy_ref: &FancyNum){ | |
997 | println!("Ref: {}", fancy_ref.num); | |
998 | } | |
999 | ``` | |
1000 | "##, | |
1001 | ||
ea8adc8c XL |
1002 | E0507: r##" |
1003 | You tried to move out of a value which was borrowed. Erroneous code example: | |
1004 | ||
1005 | ```compile_fail,E0507 | |
1006 | use std::cell::RefCell; | |
1007 | ||
1008 | struct TheDarkKnight; | |
1009 | ||
1010 | impl TheDarkKnight { | |
1011 | fn nothing_is_true(self) {} | |
1012 | } | |
1013 | ||
1014 | fn main() { | |
1015 | let x = RefCell::new(TheDarkKnight); | |
1016 | ||
1017 | x.borrow().nothing_is_true(); // error: cannot move out of borrowed content | |
1018 | } | |
1019 | ``` | |
1020 | ||
1021 | Here, the `nothing_is_true` method takes the ownership of `self`. However, | |
1022 | `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`, | |
1023 | which is a borrow of the content owned by the `RefCell`. To fix this error, | |
1024 | you 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 | ||
1030 | Examples: | |
1031 | ||
1032 | ``` | |
1033 | use std::cell::RefCell; | |
1034 | ||
1035 | struct TheDarkKnight; | |
1036 | ||
1037 | impl TheDarkKnight { | |
1038 | fn nothing_is_true(&self) {} // First case, we don't take ownership | |
1039 | } | |
1040 | ||
1041 | fn main() { | |
1042 | let x = RefCell::new(TheDarkKnight); | |
1043 | ||
1044 | x.borrow().nothing_is_true(); // ok! | |
1045 | } | |
1046 | ``` | |
1047 | ||
1048 | Or: | |
1049 | ||
1050 | ``` | |
1051 | use std::cell::RefCell; | |
1052 | ||
1053 | struct TheDarkKnight; | |
1054 | ||
1055 | impl TheDarkKnight { | |
1056 | fn nothing_is_true(self) {} | |
1057 | } | |
1058 | ||
1059 | fn 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 | ||
1067 | Or: | |
1068 | ||
1069 | ``` | |
1070 | use std::cell::RefCell; | |
1071 | ||
1072 | #[derive(Clone, Copy)] // we implement the Copy trait | |
1073 | struct TheDarkKnight; | |
1074 | ||
1075 | impl TheDarkKnight { | |
1076 | fn nothing_is_true(self) {} | |
1077 | } | |
1078 | ||
1079 | fn main() { | |
1080 | let x = RefCell::new(TheDarkKnight); | |
1081 | ||
1082 | x.borrow().nothing_is_true(); // ok! | |
1083 | } | |
1084 | ``` | |
1085 | ||
1086 | Moving a member out of a mutably borrowed struct will also cause E0507 error: | |
1087 | ||
1088 | ```compile_fail,E0507 | |
1089 | struct TheDarkKnight; | |
1090 | ||
1091 | impl TheDarkKnight { | |
1092 | fn nothing_is_true(self) {} | |
1093 | } | |
1094 | ||
1095 | struct Batcave { | |
1096 | knight: TheDarkKnight | |
1097 | } | |
1098 | ||
1099 | fn 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 | ||
1109 | It 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 } | |
1115 | use std::mem; | |
1116 | ||
1117 | let mut cave = Batcave { | |
1118 | knight: TheDarkKnight | |
1119 | }; | |
1120 | let borrowed = &mut cave; | |
1121 | ||
1122 | mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! | |
1123 | ``` | |
1124 | ||
1125 | You can find more information about borrowing in the rust-book: | |
1126 | http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html | |
1127 | "##, | |
1128 | ||
1129 | E0508: r##" | |
1130 | A value was moved out of a non-copy fixed-size array. | |
1131 | ||
1132 | Example of erroneous code: | |
1133 | ||
1134 | ```compile_fail,E0508 | |
1135 | struct NonCopy; | |
1136 | ||
1137 | fn 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 | ||
1144 | The first element was moved out of the array, but this is not | |
1145 | possible because `NonCopy` does not implement the `Copy` trait. | |
1146 | ||
1147 | Consider borrowing the element instead of moving it: | |
1148 | ||
1149 | ``` | |
1150 | struct NonCopy; | |
1151 | ||
1152 | fn main() { | |
1153 | let array = [NonCopy; 1]; | |
1154 | let _value = &array[0]; // Borrowing is allowed, unlike moving. | |
1155 | } | |
1156 | ``` | |
1157 | ||
1158 | Alternatively, if your type implements `Clone` and you need to own the value, | |
1159 | consider borrowing and then cloning: | |
1160 | ||
1161 | ``` | |
1162 | #[derive(Clone)] | |
1163 | struct NonCopy; | |
1164 | ||
1165 | fn main() { | |
1166 | let array = [NonCopy; 1]; | |
1167 | // Now you can clone the array element. | |
1168 | let _value = array[0].clone(); | |
1169 | } | |
1170 | ``` | |
1171 | "##, | |
1172 | ||
1173 | E0509: r##" | |
1174 | This error occurs when an attempt is made to move out of a value whose type | |
1175 | implements the `Drop` trait. | |
1176 | ||
1177 | Example of erroneous code: | |
1178 | ||
1179 | ```compile_fail,E0509 | |
1180 | struct FancyNum { | |
1181 | num: usize | |
1182 | } | |
1183 | ||
1184 | struct DropStruct { | |
1185 | fancy: FancyNum | |
1186 | } | |
1187 | ||
1188 | impl Drop for DropStruct { | |
1189 | fn drop(&mut self) { | |
1190 | // Destruct DropStruct, possibly using FancyNum | |
1191 | } | |
1192 | } | |
1193 | ||
1194 | fn 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 | ||
1202 | Here, we tried to move a field out of a struct of type `DropStruct` which | |
1203 | implements the `Drop` trait. However, a struct cannot be dropped if one or | |
1204 | more of its fields have been moved. | |
1205 | ||
1206 | Structs implementing the `Drop` trait have an implicit destructor that gets | |
1207 | called when they go out of scope. This destructor may use the fields of the | |
1208 | struct, so moving out of the struct could make it impossible to run the | |
1209 | destructor. Therefore, we must think of all values whose type implements the | |
1210 | `Drop` trait as single units whose fields cannot be moved. | |
1211 | ||
1212 | This error can be fixed by creating a reference to the fields of a struct, | |
1213 | enum, or tuple using the `ref` keyword: | |
1214 | ||
1215 | ``` | |
1216 | struct FancyNum { | |
1217 | num: usize | |
1218 | } | |
1219 | ||
1220 | struct DropStruct { | |
1221 | fancy: FancyNum | |
1222 | } | |
1223 | ||
1224 | impl Drop for DropStruct { | |
1225 | fn drop(&mut self) { | |
1226 | // Destruct DropStruct, possibly using FancyNum | |
1227 | } | |
1228 | } | |
1229 | ||
1230 | fn 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 | ||
1238 | Note that this technique can also be used in the arms of a match expression: | |
1239 | ||
1240 | ``` | |
1241 | struct FancyNum { | |
1242 | num: usize | |
1243 | } | |
1244 | ||
1245 | enum DropEnum { | |
1246 | Fancy(FancyNum) | |
1247 | } | |
1248 | ||
1249 | impl Drop for DropEnum { | |
1250 | fn drop(&mut self) { | |
1251 | // Destruct DropEnum, possibly using FancyNum | |
1252 | } | |
1253 | } | |
1254 | ||
1255 | fn 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 | ||
1270 | register_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 | } |