mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
parent
0486e12ad0
commit
47593dade7
@ -150,26 +150,36 @@ If you really want global mutable state, try using `static mut` or a global
|
|||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0018: r##"
|
E0018: r##"
|
||||||
The value of static and const variables must be known at compile time. You
|
|
||||||
can't cast a pointer as an integer because we can't know what value the
|
|
||||||
address will take.
|
|
||||||
|
|
||||||
However, pointers to other constants' addresses are allowed in constants,
|
The value of static and constant integers must be known at compile time. You
|
||||||
example:
|
can't cast a pointer to an integer because the address of a pointer can
|
||||||
|
vary.
|
||||||
|
|
||||||
|
For example, if you write:
|
||||||
```
|
```
|
||||||
const X: u32 = 50;
|
static MY_STATIC: u32 = 42;
|
||||||
const Y: *const u32 = &X;
|
static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
|
||||||
|
static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
|
||||||
```
|
```
|
||||||
|
|
||||||
Therefore, casting one of these non-constant pointers to an integer results
|
Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However,
|
||||||
in a non-constant integer which lead to this error. Example:
|
the address can change when the program is linked, as well as change
|
||||||
|
between different executions due to ASLR, and many linkers would
|
||||||
|
not be able to calculate the value of `WHAT`.
|
||||||
|
|
||||||
|
On the other hand, static and constant pointers can point either to
|
||||||
|
a known numeric address or to the address of a symbol.
|
||||||
|
|
||||||
```
|
```
|
||||||
const X: u32 = 1;
|
static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
|
||||||
const Y: usize = &X as *const u32 as usize;
|
// ... and also
|
||||||
println!("{}", Y);
|
static MY_STATIC_ADDR2: *const u32 = &MY_STATIC;
|
||||||
|
|
||||||
|
const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This does not pose a problem by itself because they can't be
|
||||||
|
accessed directly.
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0019: r##"
|
E0019: r##"
|
||||||
@ -347,55 +357,59 @@ From [RFC 246]:
|
|||||||
[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
|
[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
|
||||||
E0395: r##"
|
E0395: r##"
|
||||||
The value assigned to a constant expression must be known at compile time,
|
The value assigned to a constant scalar must be known at compile time,
|
||||||
which is not the case when comparing raw pointers. Erroneous code example:
|
which is not the case when comparing raw pointers.
|
||||||
|
|
||||||
|
|
||||||
|
Erroneous code example:
|
||||||
```
|
```
|
||||||
static foo: i32 = 42;
|
static FOO: i32 = 42;
|
||||||
static bar: i32 = 43;
|
static BAR: i32 = 42;
|
||||||
|
|
||||||
static baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
|
static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
|
||||||
// error: raw pointers cannot be compared in statics!
|
// error: raw pointers cannot be compared in statics!
|
||||||
```
|
```
|
||||||
|
|
||||||
Please check that the result of the comparison can be determined at compile time
|
The address assigned by the linker to `FOO` and `BAR` may or may not
|
||||||
or isn't assigned to a constant expression. Example:
|
be identical, so the value of `BAZ` can't be determined.
|
||||||
|
|
||||||
|
If you want to do the comparison, please do it at run-time.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
static foo: i32 = 42;
|
static FOO: i32 = 42;
|
||||||
static bar: i32 = 43;
|
static BAR: i32 = 42;
|
||||||
|
|
||||||
let baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
|
let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
|
||||||
// baz isn't a constant expression so it's ok
|
// baz isn't a constant expression so it's ok
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0396: r##"
|
E0396: r##"
|
||||||
The value assigned to a constant expression must be known at compile time,
|
The value behind a raw pointer can't be determined at compile-time
|
||||||
which is not the case when dereferencing raw pointers. Erroneous code
|
(or even link-time), which means it can't be used in a constant
|
||||||
example:
|
expression.
|
||||||
|
|
||||||
|
For example:
|
||||||
```
|
```
|
||||||
const foo: i32 = 42;
|
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
|
||||||
const baz: *const i32 = (&foo as *const i32);
|
|
||||||
|
|
||||||
const deref: i32 = *baz;
|
const VALUE: u8 = unsafe { *REG_ADDR };
|
||||||
// error: raw pointers cannot be dereferenced in constants
|
// error: raw pointers cannot be dereferenced in constants
|
||||||
```
|
```
|
||||||
|
|
||||||
To fix this error, please do not assign this value to a constant expression.
|
A possible fix is to dereference your pointer at some point in run-time.
|
||||||
Example:
|
|
||||||
|
For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
const foo: i32 = 42;
|
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
|
||||||
const baz: *const i32 = (&foo as *const i32);
|
|
||||||
|
|
||||||
unsafe { let deref: i32 = *baz; }
|
let reg_value = unsafe { *REG_ADDR };
|
||||||
// baz isn't a constant expression so it's ok
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You'll also note that this assignment must be done in an unsafe block!
|
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0397: r##"
|
E0397: r##"
|
||||||
|
Loading…
Reference in New Issue
Block a user