]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/diagnostics.rs
Rollup merge of #41249 - GuillaumeGomez:rustdoc-render, r=steveklabnik,frewsxcv
[rust.git] / src / librustc_mir / 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 ```compile_fail,E0010
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
33 ```compile_fail,E0013
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
69 ```compile_fail,E0016
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
84 ```compile_fail,E0017
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
110 ```compile_fail,E0018
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 ```
125 static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
126 // ... and also
127 static MY_STATIC_ADDR2: *const u32 = &MY_STATIC;
128
129 const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
130 ```
131
132 This does not pose a problem by itself because they can't be
133 accessed directly.
134 "##,
135
136 E0019: r##"
137 A function call isn't allowed in the const's initialization expression
138 because the expression's value must be known at compile-time. Erroneous code
139 example:
140
141 ```compile_fail
142 enum Test {
143     V1
144 }
145
146 impl Test {
147     fn test(&self) -> i32 {
148         12
149     }
150 }
151
152 fn main() {
153     const FOO: Test = Test::V1;
154
155     const A: i32 = FOO.test(); // You can't call Test::func() here!
156 }
157 ```
158
159 Remember: you can't use a function call inside a const's initialization
160 expression! However, you can totally use it anywhere else:
161
162 ```
163 fn main() {
164     const FOO: Test = Test::V1;
165
166     FOO.func(); // here is good
167     let x = FOO.func(); // or even here!
168 }
169 ```
170 "##,
171
172 E0022: r##"
173 Constant functions are not allowed to mutate anything. Thus, binding to an
174 argument with a mutable pattern is not allowed. For example,
175
176 ```compile_fail
177 const fn foo(mut x: u8) {
178     // do stuff
179 }
180 ```
181
182 Is incorrect because the function body may not mutate `x`.
183
184 Remove any mutable bindings from the argument list to fix this error. In case
185 you need to mutate the argument, try lazily initializing a global variable
186 instead of using a `const fn`, or refactoring the code to a functional style to
187 avoid mutation if possible.
188 "##,
189
190 E0394: r##"
191 A static was referred to by value by another static.
192
193 Erroneous code examples:
194
195 ```compile_fail,E0394
196 static A: u32 = 0;
197 static B: u32 = A; // error: cannot refer to other statics by value, use the
198                    //        address-of operator or a constant instead
199 ```
200
201 A static cannot be referred by value. To fix this issue, either use a
202 constant:
203
204 ```
205 const A: u32 = 0; // `A` is now a constant
206 static B: u32 = A; // ok!
207 ```
208
209 Or refer to `A` by reference:
210
211 ```
212 static A: u32 = 0;
213 static B: &'static u32 = &A; // ok!
214 ```
215 "##,
216
217 E0395: r##"
218 The value assigned to a constant scalar must be known at compile time,
219 which is not the case when comparing raw pointers.
220
221 Erroneous code example:
222
223 ```compile_fail,E0395
224 static FOO: i32 = 42;
225 static BAR: i32 = 42;
226
227 static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
228 // error: raw pointers cannot be compared in statics!
229 ```
230
231 The address assigned by the linker to `FOO` and `BAR` may or may not
232 be identical, so the value of `BAZ` can't be determined.
233
234 If you want to do the comparison, please do it at run-time.
235
236 For example:
237
238 ```
239 static FOO: i32 = 42;
240 static BAR: i32 = 42;
241
242 let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
243 // baz isn't a constant expression so it's ok
244 ```
245 "##,
246
247 E0161: r##"
248 A value was moved. However, its size was not known at compile time, and only
249 values of a known size can be moved.
250
251 Erroneous code example:
252
253 ```compile_fail
254 #![feature(box_syntax)]
255
256 fn main() {
257     let array: &[isize] = &[1, 2, 3];
258     let _x: Box<[isize]> = box *array;
259     // error: cannot move a value of type [isize]: the size of [isize] cannot
260     //        be statically determined
261 }
262 ```
263
264 In Rust, you can only move a value when its size is known at compile time.
265
266 To work around this restriction, consider "hiding" the value behind a reference:
267 either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
268 it around as usual. Example:
269
270 ```
271 #![feature(box_syntax)]
272
273 fn main() {
274     let array: &[isize] = &[1, 2, 3];
275     let _x: Box<&[isize]> = box array; // ok!
276 }
277 ```
278 "##,
279
280 E0396: r##"
281 The value behind a raw pointer can't be determined at compile-time
282 (or even link-time), which means it can't be used in a constant
283 expression. Erroneous code example:
284
285 ```compile_fail,E0396
286 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
287
288 const VALUE: u8 = unsafe { *REG_ADDR };
289 // error: raw pointers cannot be dereferenced in constants
290 ```
291
292 A possible fix is to dereference your pointer at some point in run-time.
293
294 For example:
295
296 ```
297 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
298
299 let reg_value = unsafe { *REG_ADDR };
300 ```
301 "##,
302
303 E0492: r##"
304 A borrow of a constant containing interior mutability was attempted. Erroneous
305 code example:
306
307 ```compile_fail,E0492
308 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
309
310 const A: AtomicUsize = ATOMIC_USIZE_INIT;
311 static B: &'static AtomicUsize = &A;
312 // error: cannot borrow a constant which contains interior mutability, create a
313 //        static instead
314 ```
315
316 A `const` represents a constant value that should never change. If one takes
317 a `&` reference to the constant, then one is taking a pointer to some memory
318 location containing the value. Normally this is perfectly fine: most values
319 can't be changed via a shared `&` pointer, but interior mutability would allow
320 it. That is, a constant value could be mutated. On the other hand, a `static` is
321 explicitly a single memory location, which can be mutated at will.
322
323 So, in order to solve this error, either use statics which are `Sync`:
324
325 ```
326 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
327
328 static A: AtomicUsize = ATOMIC_USIZE_INIT;
329 static B: &'static AtomicUsize = &A; // ok!
330 ```
331
332 You can also have this error while using a cell type:
333
334 ```compile_fail,E0492
335 #![feature(const_fn)]
336
337 use std::cell::Cell;
338
339 const A: Cell<usize> = Cell::new(1);
340 const B: &'static Cell<usize> = &A;
341 // error: cannot borrow a constant which contains interior mutability, create
342 //        a static instead
343
344 // or:
345 struct C { a: Cell<usize> }
346
347 const D: C = C { a: Cell::new(1) };
348 const E: &'static Cell<usize> = &D.a; // error
349
350 // or:
351 const F: &'static C = &D; // error
352 ```
353
354 This is because cell types do operations that are not thread-safe. Due to this,
355 they don't implement Sync and thus can't be placed in statics. In this
356 case, `StaticMutex` would work just fine, but it isn't stable yet:
357 https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
358
359 However, if you still wish to use these types, you can achieve this by an unsafe
360 wrapper:
361
362 ```
363 #![feature(const_fn)]
364
365 use std::cell::Cell;
366 use std::marker::Sync;
367
368 struct NotThreadSafe<T> {
369     value: Cell<T>,
370 }
371
372 unsafe impl<T> Sync for NotThreadSafe<T> {}
373
374 static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
375 static B: &'static NotThreadSafe<usize> = &A; // ok!
376 ```
377
378 Remember this solution is unsafe! You will have to ensure that accesses to the
379 cell are synchronized.
380 "##,
381
382 E0493: r##"
383 A type with a destructor was assigned to an invalid type of variable. Erroneous
384 code example:
385
386 ```compile_fail,E0493
387 struct Foo {
388     a: u32
389 }
390
391 impl Drop for Foo {
392     fn drop(&mut self) {}
393 }
394
395 const F : Foo = Foo { a : 0 };
396 // error: constants are not allowed to have destructors
397 static S : Foo = Foo { a : 0 };
398 // error: destructors in statics are an unstable feature
399 ```
400
401 To solve this issue, please use a type which does allow the usage of type with
402 destructors.
403 "##,
404
405 E0494: r##"
406 A reference of an interior static was assigned to another const/static.
407 Erroneous code example:
408
409 ```compile_fail,E0494
410 struct Foo {
411     a: u32
412 }
413
414 static S : Foo = Foo { a : 0 };
415 static A : &'static u32 = &S.a;
416 // error: cannot refer to the interior of another static, use a
417 //        constant instead
418 ```
419
420 The "base" variable has to be a const if you want another static/const variable
421 to refer to one of its fields. Example:
422
423 ```
424 struct Foo {
425     a: u32
426 }
427
428 const S : Foo = Foo { a : 0 };
429 static A : &'static u32 = &S.a; // ok!
430 ```
431 "##,
432
433 }
434
435 register_diagnostics! {
436     E0526, // shuffle indices are not constant
437 }