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:
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!
219 The value assigned to a constant scalar must be known at compile time,
220 which is not the case when comparing raw pointers.
222 Erroneous code example:
225 static FOO: i32 = 42;
226 static BAR: i32 = 42;
228 static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
229 // error: raw pointers cannot be compared in statics!
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.
235 If you want to do the comparison, please do it at run-time.
240 static FOO: i32 = 42;
241 static BAR: i32 = 42;
243 let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
244 // baz isn't a constant expression so it's ok
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:
254 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
256 const VALUE: u8 = unsafe { *REG_ADDR };
257 // error: raw pointers cannot be dereferenced in constants
260 A possible fix is to dereference your pointer at some point in run-time.
265 const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
267 let reg_value = unsafe { *REG_ADDR };
272 A borrow of a constant containing interior mutability was attempted. Erroneous
276 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
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
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.
291 So, in order to solve this error, either use statics which are `Sync`:
294 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
296 static A: AtomicUsize = ATOMIC_USIZE_INIT;
297 static B: &'static AtomicUsize = &A; // ok!
300 You can also have this error while using a cell type:
303 #![feature(const_fn)]
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
313 struct C { a: Cell<usize> }
315 const D: C = C { a: Cell::new(1) };
316 const E: &'static Cell<usize> = &D.a; // error
319 const F: &'static C = &D; // error
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
327 However, if you still wish to use these types, you can achieve this by an unsafe
331 #![feature(const_fn)]
334 use std::marker::Sync;
336 struct NotThreadSafe<T> {
340 unsafe impl<T> Sync for NotThreadSafe<T> {}
342 static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
343 static B: &'static NotThreadSafe<usize> = &A; // ok!
346 Remember this solution is unsafe! You will have to ensure that accesses to the
347 cell are synchronized.
351 A type with a destructor was assigned to an invalid type of variable. Erroneous
360 fn drop(&mut self) {}
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
369 To solve this issue, please use a type which does allow the usage of type with
374 A reference of an interior static was assigned to another const/static.
375 Erroneous code example:
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
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:
396 const S : Foo = Foo { a : 0 };
397 static A : &'static u32 = &S.a; // ok!
403 register_diagnostics! {
404 E0526, // shuffle indices are not constant