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