]> git.lizzy.rs Git - rust.git/blob - src/librustc_passes/diagnostics.rs
Rollup merge of #31031 - brson:issue-30123, r=nikomatsakis
[rust.git] / src / librustc_passes / diagnostics.rs
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
21 ```
22 #![feature(box_syntax)]
23
24 const CON : Box<i32> = box 0;
25 ```
26 "##,
27
28 E0011: r##"
29 Initializers for constants and statics are evaluated at compile time.
30 User-defined operators rely on user-defined functions, which cannot be evaluated
31 at compile time.
32
33 Bad example:
34
35 ```
36 use std::ops::Index;
37
38 struct Foo { a: u8 }
39
40 impl Index<u8> for Foo {
41     type Output = u8;
42
43     fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
44 }
45
46 const a: Foo = Foo { a: 0u8 };
47 const b: u8 = a[0]; // Index trait is defined by the user, bad!
48 ```
49
50 Only operators on builtin types are allowed.
51
52 Example:
53
54 ```
55 const a: &'static [i32] = &[1, 2, 3];
56 const b: i32 = a[0]; // Good!
57 ```
58 "##,
59
60 E0013: r##"
61 Static and const variables can refer to other const variables. But a const
62 variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
63 here:
64
65 ```
66 static X: i32 = 42;
67 const Y: i32 = X;
68 ```
69
70 To fix this, the value can be extracted as a const and then used:
71
72 ```
73 const A: i32 = 42;
74 static X: i32 = A;
75 const Y: i32 = A;
76 ```
77 "##,
78
79 E0014: r##"
80 Constants can only be initialized by a constant value or, in a future
81 version of Rust, a call to a const function. This error indicates the use
82 of a path (like a::b, or x) denoting something other than one of these
83 allowed items. Example:
84
85 ```
86 const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
87 ```
88
89 To avoid it, you have to replace the non-constant value:
90
91 ```
92 const FOO: i32 = { const X : i32 = 0; X };
93 // or even:
94 const FOO: i32 = { 0 }; // but brackets are useless here
95 ```
96 "##,
97
98 // FIXME(#24111) Change the language here when const fn stabilizes
99 E0015: r##"
100 The only functions that can be called in static or constant expressions are
101 `const` functions, and struct/enum constructors. `const` functions are only
102 available on a nightly compiler. Rust currently does not support more general
103 compile-time function execution.
104
105 ```
106 const FOO: Option<u8> = Some(1); // enum constructor
107 struct Bar {x: u8}
108 const BAR: Bar = Bar {x: 1}; // struct constructor
109 ```
110
111 See [RFC 911] for more details on the design of `const fn`s.
112
113 [RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
114 "##,
115
116 E0016: r##"
117 Blocks in constants may only contain items (such as constant, function
118 definition, etc...) and a tail expression. Example:
119
120 ```
121 const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
122 ```
123
124 To avoid it, you have to replace the non-item object:
125
126 ```
127 const FOO: i32 = { const X : i32 = 0; X };
128 ```
129 "##,
130
131 E0017: r##"
132 References in statics and constants may only refer to immutable values. Example:
133
134 ```
135 static X: i32 = 1;
136 const C: i32 = 2;
137
138 // these three are not allowed:
139 const CR: &'static mut i32 = &mut C;
140 static STATIC_REF: &'static mut i32 = &mut X;
141 static CONST_REF: &'static mut i32 = &mut C;
142 ```
143
144 Statics are shared everywhere, and if they refer to mutable data one might
145 violate memory safety since holding multiple mutable references to shared data
146 is not allowed.
147
148 If you really want global mutable state, try using `static mut` or a global
149 `UnsafeCell`.
150 "##,
151
152 E0018: r##"
153 The value of static and const variables must be known at compile time. You
154 can't cast a pointer as an integer because we can't know what value the
155 address will take.
156
157 However, pointers to other constants' addresses are allowed in constants,
158 example:
159
160 ```
161 const X: u32 = 50;
162 const Y: *const u32 = &X;
163 ```
164
165 Therefore, casting one of these non-constant pointers to an integer results
166 in a non-constant integer which lead to this error. Example:
167
168 ```
169 const X: u32 = 1;
170 const Y: usize = &X as *const u32 as usize;
171 println!("{}", Y);
172 ```
173 "##,
174
175 E0019: r##"
176 A function call isn't allowed in the const's initialization expression
177 because the expression's value must be known at compile-time. Example of
178 erroneous code:
179
180 ```
181 enum Test {
182     V1
183 }
184
185 impl Test {
186     fn test(&self) -> i32 {
187         12
188     }
189 }
190
191 fn main() {
192     const FOO: Test = Test::V1;
193
194     const A: i32 = FOO.test(); // You can't call Test::func() here !
195 }
196 ```
197
198 Remember: you can't use a function call inside a const's initialization
199 expression! However, you can totally use it anywhere else:
200
201 ```
202 fn main() {
203     const FOO: Test = Test::V1;
204
205     FOO.func(); // here is good
206     let x = FOO.func(); // or even here!
207 }
208 ```
209 "##,
210
211 E0022: r##"
212 Constant functions are not allowed to mutate anything. Thus, binding to an
213 argument with a mutable pattern is not allowed. For example,
214
215 ```
216 const fn foo(mut x: u8) {
217     // do stuff
218 }
219 ```
220
221 is bad because the function body may not mutate `x`.
222
223 Remove any mutable bindings from the argument list to fix this error. In case
224 you need to mutate the argument, try lazily initializing a global variable
225 instead of using a `const fn`, or refactoring the code to a functional style to
226 avoid mutation if possible.
227 "##,
228
229 E0030: r##"
230 When matching against a range, the compiler verifies that the range is
231 non-empty.  Range patterns include both end-points, so this is equivalent to
232 requiring the start of the range to be less than or equal to the end of the
233 range.
234
235 For example:
236
237 ```
238 match 5u32 {
239     // This range is ok, albeit pointless.
240     1 ... 1 => ...
241     // This range is empty, and the compiler can tell.
242     1000 ... 5 => ...
243 }
244 ```
245 "##,
246
247 E0161: r##"
248 In Rust, you can only move a value when its size is known at compile time.
249
250 To work around this restriction, consider "hiding" the value behind a reference:
251 either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
252 it around as usual.
253 "##,
254
255 E0265: r##"
256 This error indicates that a static or constant references itself.
257 All statics and constants need to resolve to a value in an acyclic manner.
258
259 For example, neither of the following can be sensibly compiled:
260
261 ```
262 const X: u32 = X;
263 ```
264
265 ```
266 const X: u32 = Y;
267 const Y: u32 = X;
268 ```
269 "##,
270
271 E0267: r##"
272 This error indicates the use of a loop keyword (`break` or `continue`) inside a
273 closure but outside of any loop. Erroneous code example:
274
275 ```
276 let w = || { break; }; // error: `break` inside of a closure
277 ```
278
279 `break` and `continue` keywords can be used as normal inside closures as long as
280 they are also contained within a loop. To halt the execution of a closure you
281 should instead use a return statement. Example:
282
283 ```
284 let w = || {
285     for _ in 0..10 {
286         break;
287     }
288 };
289
290 w();
291 ```
292 "##,
293
294 E0268: r##"
295 This error indicates the use of a loop keyword (`break` or `continue`) outside
296 of a loop. Without a loop to break out of or continue in, no sensible action can
297 be taken. Erroneous code example:
298
299 ```
300 fn some_func() {
301     break; // error: `break` outside of loop
302 }
303 ```
304
305 Please verify that you are using `break` and `continue` only in loops. Example:
306
307 ```
308 fn some_func() {
309     for _ in 0..10 {
310         break; // ok!
311     }
312 }
313 ```
314 "##,
315
316 E0378: r##"
317 Method calls that aren't calls to inherent `const` methods are disallowed
318 in statics, constants, and constant functions.
319
320 For example:
321
322 ```
323 const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
324
325 struct Foo(i32);
326
327 impl Foo {
328     const fn foo(&self) -> i32 {
329         self.bar() // error, `bar` isn't `const`
330     }
331
332     fn bar(&self) -> i32 { self.0 }
333 }
334 ```
335
336 For more information about `const fn`'s, see [RFC 911].
337
338 [RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
339 "##,
340
341 E0394: r##"
342 From [RFC 246]:
343
344  > It is invalid for a static to reference another static by value. It is
345  > required that all references be borrowed.
346
347 [RFC 246]: https://github.com/rust-lang/rfcs/pull/246
348 "##,
349
350 E0395: r##"
351 The value assigned to a constant expression must be known at compile time,
352 which is not the case when comparing raw pointers. Erroneous code example:
353
354 ```
355 static foo: i32 = 42;
356 static bar: i32 = 43;
357
358 static baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
359 // error: raw pointers cannot be compared in statics!
360 ```
361
362 Please check that the result of the comparison can be determined at compile time
363 or isn't assigned to a constant expression. Example:
364
365 ```
366 static foo: i32 = 42;
367 static bar: i32 = 43;
368
369 let baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
370 // baz isn't a constant expression so it's ok
371 ```
372 "##,
373
374 E0396: r##"
375 The value assigned to a constant expression must be known at compile time,
376 which is not the case when dereferencing raw pointers. Erroneous code
377 example:
378
379 ```
380 const foo: i32 = 42;
381 const baz: *const i32 = (&foo as *const i32);
382
383 const deref: i32 = *baz;
384 // error: raw pointers cannot be dereferenced in constants
385 ```
386
387 To fix this error, please do not assign this value to a constant expression.
388 Example:
389
390 ```
391 const foo: i32 = 42;
392 const baz: *const i32 = (&foo as *const i32);
393
394 unsafe { let deref: i32 = *baz; }
395 // baz isn't a constant expression so it's ok
396 ```
397
398 You'll also note that this assignment must be done in an unsafe block!
399 "##,
400
401 E0397: r##"
402 It is not allowed for a mutable static to allocate or have destructors. For
403 example:
404
405 ```
406 // error: mutable statics are not allowed to have boxes
407 static mut FOO: Option<Box<usize>> = None;
408
409 // error: mutable statics are not allowed to have destructors
410 static mut BAR: Option<Vec<i32>> = None;
411 ```
412 "##,
413
414 E0400: r##"
415 A user-defined dereference was attempted in an invalid context. Erroneous
416 code example:
417
418 ```
419 use std::ops::Deref;
420
421 struct A;
422
423 impl Deref for A {
424     type Target = str;
425
426     fn deref(&self)-> &str { "foo" }
427 }
428
429 const S: &'static str = &A;
430 // error: user-defined dereference operators are not allowed in constants
431
432 fn main() {
433     let foo = S;
434 }
435 ```
436
437 You cannot directly use a dereference operation whilst initializing a constant
438 or a static. To fix this error, restructure your code to avoid this dereference,
439 perhaps moving it inline:
440
441 ```
442 use std::ops::Deref;
443
444 struct A;
445
446 impl Deref for A {
447     type Target = str;
448
449     fn deref(&self)-> &str { "foo" }
450 }
451
452 fn main() {
453     let foo : &str = &A;
454 }
455 ```
456 "##,
457
458 E0492: r##"
459 A borrow of a constant containing interior mutability was attempted. Erroneous
460 code example:
461
462 ```
463 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
464
465 const A: AtomicUsize = ATOMIC_USIZE_INIT;
466 static B: &'static AtomicUsize = &A;
467 // error: cannot borrow a constant which contains interior mutability, create a
468 //        static instead
469 ```
470
471 A `const` represents a constant value that should never change. If one takes
472 a `&` reference to the constant, then one is taking a pointer to some memory
473 location containing the value. Normally this is perfectly fine: most values
474 can't be changed via a shared `&` pointer, but interior mutability would allow
475 it. That is, a constant value could be mutated. On the other hand, a `static` is
476 explicitly a single memory location, which can be mutated at will.
477
478 So, in order to solve this error, either use statics which are `Sync`:
479
480 ```
481 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
482
483 static A: AtomicUsize = ATOMIC_USIZE_INIT;
484 static B: &'static AtomicUsize = &A; // ok!
485 ```
486
487 You can also have this error while using a cell type:
488
489 ```
490 #![feature(const_fn)]
491
492 use std::cell::Cell;
493
494 const A: Cell<usize> = Cell::new(1);
495 const B: &'static Cell<usize> = &A;
496 // error: cannot borrow a constant which contains interior mutability, create
497 //        a static instead
498
499 // or:
500 struct C { a: Cell<usize> }
501
502 const D: C = C { a: Cell::new(1) };
503 const E: &'static Cell<usize> = &D.a; // error
504
505 // or:
506 const F: &'static C = &D; // error
507 ```
508
509 This is because cell types do operations that are not thread-safe. Due to this,
510 they don't implement Sync and thus can't be placed in statics. In this
511 case, `StaticMutex` would work just fine, but it isn't stable yet:
512 https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
513
514 However, if you still wish to use these types, you can achieve this by an unsafe
515 wrapper:
516
517 ```
518 #![feature(const_fn)]
519
520 use std::cell::Cell;
521 use std::marker::Sync;
522
523 struct NotThreadSafe<T> {
524     value: Cell<T>,
525 }
526
527 unsafe impl<T> Sync for NotThreadSafe<T> {}
528
529 static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
530 static B: &'static NotThreadSafe<usize> = &A; // ok!
531 ```
532
533 Remember this solution is unsafe! You will have to ensure that accesses to the
534 cell are synchronized.
535 "##,
536
537 E0493: r##"
538 A type with a destructor was assigned to an invalid type of variable. Erroneous
539 code example:
540
541 ```
542 struct Foo {
543     a: u32
544 }
545
546 impl Drop for Foo {
547     fn drop(&mut self) {}
548 }
549
550 const F : Foo = Foo { a : 0 };
551 // error: constants are not allowed to have destructors
552 static S : Foo = Foo { a : 0 };
553 // error: statics are not allowed to have destructors
554 ```
555
556 To solve this issue, please use a type which does allow the usage of type with
557 destructors.
558 "##,
559
560 E0494: r##"
561 A reference of an interior static was assigned to another const/static.
562 Erroneous code example:
563
564 ```
565 struct Foo {
566     a: u32
567 }
568
569 static S : Foo = Foo { a : 0 };
570 static A : &'static u32 = &S.a;
571 // error: cannot refer to the interior of another static, use a
572 //        constant instead
573 ```
574
575 The "base" variable has to be a const if you want another static/const variable
576 to refer to one of its fields. Example:
577
578 ```
579 struct Foo {
580     a: u32
581 }
582
583 const S : Foo = Foo { a : 0 };
584 static A : &'static u32 = &S.a; // ok!
585 ```
586 "##,
587
588 }
589
590 register_diagnostics! {
591     E0472, // asm! is unsupported on this target
592 }