]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/diagnostics.rs
Rollup merge of #35670 - RockyTV:e0365, r=jonathandturner
[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
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
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
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
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
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
218 E0395: r##"
219 The value assigned to a constant scalar must be known at compile time,
220 which is not the case when comparing raw pointers.
221
222 Erroneous code example:
223
224 ```compile_fail
225 static FOO: i32 = 42;
226 static BAR: i32 = 42;
227
228 static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
229 // error: raw pointers cannot be compared in statics!
230 ```
231
232 The address assigned by the linker to `FOO` and `BAR` may or may not
233 be identical, so the value of `BAZ` can't be determined.
234
235 If you want to do the comparison, please do it at run-time.
236
237 For example:
238
239 ```
240 static FOO: i32 = 42;
241 static BAR: i32 = 42;
242
243 let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
244 // baz isn't a constant expression so it's ok
245 ```
246 "##,
247
248 E0396: r##"
249 The value behind a raw pointer can't be determined at compile-time
250 (or even link-time), which means it can't be used in a constant
251 expression. Erroneous code example:
252
253 ```compile_fail
254 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
255
256 const VALUE: u8 = unsafe { *REG_ADDR };
257 // error: raw pointers cannot be dereferenced in constants
258 ```
259
260 A possible fix is to dereference your pointer at some point in run-time.
261
262 For example:
263
264 ```
265 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
266
267 let reg_value = unsafe { *REG_ADDR };
268 ```
269 "##,
270
271 E0492: r##"
272 A borrow of a constant containing interior mutability was attempted. Erroneous
273 code example:
274
275 ```compile_fail
276 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
277
278 const A: AtomicUsize = ATOMIC_USIZE_INIT;
279 static B: &'static AtomicUsize = &A;
280 // error: cannot borrow a constant which contains interior mutability, create a
281 //        static instead
282 ```
283
284 A `const` represents a constant value that should never change. If one takes
285 a `&` reference to the constant, then one is taking a pointer to some memory
286 location containing the value. Normally this is perfectly fine: most values
287 can't be changed via a shared `&` pointer, but interior mutability would allow
288 it. That is, a constant value could be mutated. On the other hand, a `static` is
289 explicitly a single memory location, which can be mutated at will.
290
291 So, in order to solve this error, either use statics which are `Sync`:
292
293 ```
294 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
295
296 static A: AtomicUsize = ATOMIC_USIZE_INIT;
297 static B: &'static AtomicUsize = &A; // ok!
298 ```
299
300 You can also have this error while using a cell type:
301
302 ```compile_fail
303 #![feature(const_fn)]
304
305 use std::cell::Cell;
306
307 const A: Cell<usize> = Cell::new(1);
308 const B: &'static Cell<usize> = &A;
309 // error: cannot borrow a constant which contains interior mutability, create
310 //        a static instead
311
312 // or:
313 struct C { a: Cell<usize> }
314
315 const D: C = C { a: Cell::new(1) };
316 const E: &'static Cell<usize> = &D.a; // error
317
318 // or:
319 const F: &'static C = &D; // error
320 ```
321
322 This is because cell types do operations that are not thread-safe. Due to this,
323 they don't implement Sync and thus can't be placed in statics. In this
324 case, `StaticMutex` would work just fine, but it isn't stable yet:
325 https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
326
327 However, if you still wish to use these types, you can achieve this by an unsafe
328 wrapper:
329
330 ```
331 #![feature(const_fn)]
332
333 use std::cell::Cell;
334 use std::marker::Sync;
335
336 struct NotThreadSafe<T> {
337     value: Cell<T>,
338 }
339
340 unsafe impl<T> Sync for NotThreadSafe<T> {}
341
342 static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
343 static B: &'static NotThreadSafe<usize> = &A; // ok!
344 ```
345
346 Remember this solution is unsafe! You will have to ensure that accesses to the
347 cell are synchronized.
348 "##,
349
350 E0493: r##"
351 A type with a destructor was assigned to an invalid type of variable. Erroneous
352 code example:
353
354 ```compile_fail
355 struct Foo {
356     a: u32
357 }
358
359 impl Drop for Foo {
360     fn drop(&mut self) {}
361 }
362
363 const F : Foo = Foo { a : 0 };
364 // error: constants are not allowed to have destructors
365 static S : Foo = Foo { a : 0 };
366 // error: destructors in statics are an unstable feature
367 ```
368
369 To solve this issue, please use a type which does allow the usage of type with
370 destructors.
371 "##,
372
373 E0494: r##"
374 A reference of an interior static was assigned to another const/static.
375 Erroneous code example:
376
377 ```compile_fail
378 struct Foo {
379     a: u32
380 }
381
382 static S : Foo = Foo { a : 0 };
383 static A : &'static u32 = &S.a;
384 // error: cannot refer to the interior of another static, use a
385 //        constant instead
386 ```
387
388 The "base" variable has to be a const if you want another static/const variable
389 to refer to one of its fields. Example:
390
391 ```
392 struct Foo {
393     a: u32
394 }
395
396 const S : Foo = Foo { a : 0 };
397 static A : &'static u32 = &S.a; // ok!
398 ```
399 "##,
400
401 }
402
403 register_diagnostics! {
404     E0526, // shuffle indices are not constant
405 }