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.
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.
11 #![allow(non_snake_case)]
13 register_long_diagnostics! {
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
22 #![feature(box_syntax)]
24 const CON : Box<i32> = box 0;
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
38 To fix this, the value can be extracted as a const and then used:
47 // FIXME(#24111) Change the language here when const fn stabilizes
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.
55 const FOO: Option<u8> = Some(1); // enum constructor
57 const BAR: Bar = Bar {x: 1}; // struct constructor
60 See [RFC 911] for more details on the design of `const fn`s.
62 [RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
66 Blocks in constants may only contain items (such as constant, function
67 definition, etc...) and a tail expression. Erroneous code example:
70 const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
73 To avoid it, you have to replace the non-item object:
76 const FOO: i32 = { const X : i32 = 0; X };
81 References in statics and constants may only refer to immutable values.
82 Erroneous code example:
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;
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
98 If you really want global mutable state, try using `static mut` or a global
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
108 For example, if you write:
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;
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`.
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.
125 static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
127 static MY_STATIC_ADDR2: *const u32 = &MY_STATIC;
129 const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
132 This does not pose a problem by itself because they can't be
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
147 fn test(&self) -> i32 {
153 const FOO: Test = Test::V1;
155 const A: i32 = FOO.test(); // You can't call Test::func() here!
159 Remember: you can't use a function call inside a const's initialization
160 expression! However, you can totally use it anywhere else:
164 const FOO: Test = Test::V1;
166 FOO.func(); // here is good
167 let x = FOO.func(); // or even here!
173 Constant functions are not allowed to mutate anything. Thus, binding to an
174 argument with a mutable pattern is not allowed. For example,
177 const fn foo(mut x: u8) {
182 Is incorrect because the function body may not mutate `x`.
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.
191 A static was referred to by value by another static.
193 Erroneous code examples:
195 ```compile_fail,E0394
197 static B: u32 = A; // error: cannot refer to other statics by value, use the
198 // address-of operator or a constant instead
201 A static cannot be referred by value. To fix this issue, either use a
205 const A: u32 = 0; // `A` is now a constant
206 static B: u32 = A; // ok!
209 Or refer to `A` by reference:
213 static B: &'static u32 = &A; // ok!
218 The value assigned to a constant scalar must be known at compile time,
219 which is not the case when comparing raw pointers.
221 Erroneous code example:
223 ```compile_fail,E0395
224 static FOO: i32 = 42;
225 static BAR: i32 = 42;
227 static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
228 // error: raw pointers cannot be compared in statics!
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.
234 If you want to do the comparison, please do it at run-time.
239 static FOO: i32 = 42;
240 static BAR: i32 = 42;
242 let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
243 // baz isn't a constant expression so it's ok
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.
251 Erroneous code example:
254 #![feature(box_syntax)]
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
264 In Rust, you can only move a value when its size is known at compile time.
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:
271 #![feature(box_syntax)]
274 let array: &[isize] = &[1, 2, 3];
275 let _x: Box<&[isize]> = box array; // ok!
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:
285 ```compile_fail,E0396
286 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
288 const VALUE: u8 = unsafe { *REG_ADDR };
289 // error: raw pointers cannot be dereferenced in constants
292 A possible fix is to dereference your pointer at some point in run-time.
297 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
299 let reg_value = unsafe { *REG_ADDR };
304 A borrow of a constant containing interior mutability was attempted. Erroneous
307 ```compile_fail,E0492
308 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
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
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.
323 So, in order to solve this error, either use statics which are `Sync`:
326 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
328 static A: AtomicUsize = ATOMIC_USIZE_INIT;
329 static B: &'static AtomicUsize = &A; // ok!
332 You can also have this error while using a cell type:
334 ```compile_fail,E0492
335 #![feature(const_fn)]
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
345 struct C { a: Cell<usize> }
347 const D: C = C { a: Cell::new(1) };
348 const E: &'static Cell<usize> = &D.a; // error
351 const F: &'static C = &D; // error
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
359 However, if you still wish to use these types, you can achieve this by an unsafe
363 #![feature(const_fn)]
366 use std::marker::Sync;
368 struct NotThreadSafe<T> {
372 unsafe impl<T> Sync for NotThreadSafe<T> {}
374 static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
375 static B: &'static NotThreadSafe<usize> = &A; // ok!
378 Remember this solution is unsafe! You will have to ensure that accesses to the
379 cell are synchronized.
383 A type with a destructor was assigned to an invalid type of variable. Erroneous
386 ```compile_fail,E0493
392 fn drop(&mut self) {}
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
401 To solve this issue, please use a type which does allow the usage of type with
406 A reference of an interior static was assigned to another const/static.
407 Erroneous code example:
409 ```compile_fail,E0494
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
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:
428 const S : Foo = Foo { a : 0 };
429 static A : &'static u32 = &S.a; // ok!
435 register_diagnostics! {
436 E0526, // shuffle indices are not constant