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 Initializers for constants and statics are evaluated at compile time.
30 User-defined operators rely on user-defined functions, which cannot be evaluated
40 impl Index<u8> for Foo {
43 fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
46 const a: Foo = Foo { a: 0u8 };
47 const b: u8 = a[0]; // Index trait is defined by the user, bad!
50 Only operators on builtin types are allowed.
55 const a: &'static [i32] = &[1, 2, 3];
56 const b: i32 = a[0]; // Good!
61 Static and const variables can refer to other const variables. But a const
62 variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
70 To fix this, the value can be extracted as a const and then used:
80 Constants can only be initialized by a constant value or, in a future
81 version of Rust, a call to a const function. This error indicates the use
82 of a path (like a::b, or x) denoting something other than one of these
83 allowed items. Example:
86 const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
89 To avoid it, you have to replace the non-constant value:
92 const FOO: i32 = { const X : i32 = 0; X };
94 const FOO: i32 = { 0 }; // but brackets are useless here
98 // FIXME(#24111) Change the language here when const fn stabilizes
100 The only functions that can be called in static or constant expressions are
101 `const` functions, and struct/enum constructors. `const` functions are only
102 available on a nightly compiler. Rust currently does not support more general
103 compile-time function execution.
106 const FOO: Option<u8> = Some(1); // enum constructor
108 const BAR: Bar = Bar {x: 1}; // struct constructor
111 See [RFC 911] for more details on the design of `const fn`s.
113 [RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
117 Blocks in constants may only contain items (such as constant, function
118 definition, etc...) and a tail expression. Example:
121 const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
124 To avoid it, you have to replace the non-item object:
127 const FOO: i32 = { const X : i32 = 0; X };
132 References in statics and constants may only refer to immutable values. Example:
138 // these three are not allowed:
139 const CR: &'static mut i32 = &mut C;
140 static STATIC_REF: &'static mut i32 = &mut X;
141 static CONST_REF: &'static mut i32 = &mut C;
144 Statics are shared everywhere, and if they refer to mutable data one might
145 violate memory safety since holding multiple mutable references to shared data
148 If you really want global mutable state, try using `static mut` or a global
153 The value of static and const variables must be known at compile time. You
154 can't cast a pointer as an integer because we can't know what value the
157 However, pointers to other constants' addresses are allowed in constants,
162 const Y: *const u32 = &X;
165 Therefore, casting one of these non-constant pointers to an integer results
166 in a non-constant integer which lead to this error. Example:
170 const Y: usize = &X as *const u32 as usize;
176 A function call isn't allowed in the const's initialization expression
177 because the expression's value must be known at compile-time. Example of
186 fn test(&self) -> i32 {
192 const FOO: Test = Test::V1;
194 const A: i32 = FOO.test(); // You can't call Test::func() here !
198 Remember: you can't use a function call inside a const's initialization
199 expression! However, you can totally use it anywhere else:
203 const FOO: Test = Test::V1;
205 FOO.func(); // here is good
206 let x = FOO.func(); // or even here!
212 Constant functions are not allowed to mutate anything. Thus, binding to an
213 argument with a mutable pattern is not allowed. For example,
216 const fn foo(mut x: u8) {
221 is bad because the function body may not mutate `x`.
223 Remove any mutable bindings from the argument list to fix this error. In case
224 you need to mutate the argument, try lazily initializing a global variable
225 instead of using a `const fn`, or refactoring the code to a functional style to
226 avoid mutation if possible.
230 When matching against a range, the compiler verifies that the range is
231 non-empty. Range patterns include both end-points, so this is equivalent to
232 requiring the start of the range to be less than or equal to the end of the
239 // This range is ok, albeit pointless.
241 // This range is empty, and the compiler can tell.
248 In Rust, you can only move a value when its size is known at compile time.
250 To work around this restriction, consider "hiding" the value behind a reference:
251 either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
256 This error indicates that a static or constant references itself.
257 All statics and constants need to resolve to a value in an acyclic manner.
259 For example, neither of the following can be sensibly compiled:
272 This error indicates the use of a loop keyword (`break` or `continue`) inside a
273 closure but outside of any loop. Erroneous code example:
276 let w = || { break; }; // error: `break` inside of a closure
279 `break` and `continue` keywords can be used as normal inside closures as long as
280 they are also contained within a loop. To halt the execution of a closure you
281 should instead use a return statement. Example:
295 This error indicates the use of a loop keyword (`break` or `continue`) outside
296 of a loop. Without a loop to break out of or continue in, no sensible action can
297 be taken. Erroneous code example:
301 break; // error: `break` outside of loop
305 Please verify that you are using `break` and `continue` only in loops. Example:
317 Method calls that aren't calls to inherent `const` methods are disallowed
318 in statics, constants, and constant functions.
323 const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
328 const fn foo(&self) -> i32 {
329 self.bar() // error, `bar` isn't `const`
332 fn bar(&self) -> i32 { self.0 }
336 For more information about `const fn`'s, see [RFC 911].
338 [RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
344 > It is invalid for a static to reference another static by value. It is
345 > required that all references be borrowed.
347 [RFC 246]: https://github.com/rust-lang/rfcs/pull/246
351 The value assigned to a constant expression must be known at compile time,
352 which is not the case when comparing raw pointers. Erroneous code example:
355 static foo: i32 = 42;
356 static bar: i32 = 43;
358 static baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
359 // error: raw pointers cannot be compared in statics!
362 Please check that the result of the comparison can be determined at compile time
363 or isn't assigned to a constant expression. Example:
366 static foo: i32 = 42;
367 static bar: i32 = 43;
369 let baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
370 // baz isn't a constant expression so it's ok
375 The value assigned to a constant expression must be known at compile time,
376 which is not the case when dereferencing raw pointers. Erroneous code
381 const baz: *const i32 = (&foo as *const i32);
383 const deref: i32 = *baz;
384 // error: raw pointers cannot be dereferenced in constants
387 To fix this error, please do not assign this value to a constant expression.
392 const baz: *const i32 = (&foo as *const i32);
394 unsafe { let deref: i32 = *baz; }
395 // baz isn't a constant expression so it's ok
398 You'll also note that this assignment must be done in an unsafe block!
402 It is not allowed for a mutable static to allocate or have destructors. For
406 // error: mutable statics are not allowed to have boxes
407 static mut FOO: Option<Box<usize>> = None;
409 // error: mutable statics are not allowed to have destructors
410 static mut BAR: Option<Vec<i32>> = None;
415 A user-defined dereference was attempted in an invalid context. Erroneous
426 fn deref(&self)-> &str { "foo" }
429 const S: &'static str = &A;
430 // error: user-defined dereference operators are not allowed in constants
437 You cannot directly use a dereference operation whilst initializing a constant
438 or a static. To fix this error, restructure your code to avoid this dereference,
439 perhaps moving it inline:
449 fn deref(&self)-> &str { "foo" }
459 A borrow of a constant containing interior mutability was attempted. Erroneous
463 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
465 const A: AtomicUsize = ATOMIC_USIZE_INIT;
466 static B: &'static AtomicUsize = &A;
467 // error: cannot borrow a constant which contains interior mutability, create a
471 A `const` represents a constant value that should never change. If one takes
472 a `&` reference to the constant, then one is taking a pointer to some memory
473 location containing the value. Normally this is perfectly fine: most values
474 can't be changed via a shared `&` pointer, but interior mutability would allow
475 it. That is, a constant value could be mutated. On the other hand, a `static` is
476 explicitly a single memory location, which can be mutated at will.
478 So, in order to solve this error, either use statics which are `Sync`:
481 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
483 static A: AtomicUsize = ATOMIC_USIZE_INIT;
484 static B: &'static AtomicUsize = &A; // ok!
487 You can also have this error while using a cell type:
490 #![feature(const_fn)]
494 const A: Cell<usize> = Cell::new(1);
495 const B: &'static Cell<usize> = &A;
496 // error: cannot borrow a constant which contains interior mutability, create
500 struct C { a: Cell<usize> }
502 const D: C = C { a: Cell::new(1) };
503 const E: &'static Cell<usize> = &D.a; // error
506 const F: &'static C = &D; // error
509 This is because cell types do operations that are not thread-safe. Due to this,
510 they don't implement Sync and thus can't be placed in statics. In this
511 case, `StaticMutex` would work just fine, but it isn't stable yet:
512 https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
514 However, if you still wish to use these types, you can achieve this by an unsafe
518 #![feature(const_fn)]
521 use std::marker::Sync;
523 struct NotThreadSafe<T> {
527 unsafe impl<T> Sync for NotThreadSafe<T> {}
529 static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
530 static B: &'static NotThreadSafe<usize> = &A; // ok!
533 Remember this solution is unsafe! You will have to ensure that accesses to the
534 cell are synchronized.
538 A type with a destructor was assigned to an invalid type of variable. Erroneous
547 fn drop(&mut self) {}
550 const F : Foo = Foo { a : 0 };
551 // error: constants are not allowed to have destructors
552 static S : Foo = Foo { a : 0 };
553 // error: statics are not allowed to have destructors
556 To solve this issue, please use a type which does allow the usage of type with
561 A reference of an interior static was assigned to another const/static.
562 Erroneous code example:
569 static S : Foo = Foo { a : 0 };
570 static A : &'static u32 = &S.a;
571 // error: cannot refer to the interior of another static, use a
575 The "base" variable has to be a const if you want another static/const variable
576 to refer to one of its fields. Example:
583 const S : Foo = Foo { a : 0 };
584 static A : &'static u32 = &S.a; // ok!
590 register_diagnostics! {
591 E0472, // asm! is unsupported on this target