Skip to content

Commit 47593da

Browse files
committed
Improve the error explanations for check_const
Fixes #30705
1 parent 0486e12 commit 47593da

File tree

1 file changed

+50
-36
lines changed

1 file changed

+50
-36
lines changed

src/librustc_passes/diagnostics.rs

+50-36
Original file line numberDiff line numberDiff line change
@@ -150,26 +150,36 @@ If you really want global mutable state, try using `static mut` or a global
150150
"##,
151151

152152
E0018: r##"
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
155-
address will take.
156153
157-
However, pointers to other constants' addresses are allowed in constants,
158-
example:
154+
The value of static and constant integers must be known at compile time. You
155+
can't cast a pointer to an integer because the address of a pointer can
156+
vary.
159157
158+
For example, if you write:
160159
```
161-
const X: u32 = 50;
162-
const Y: *const u32 = &X;
160+
static MY_STATIC: u32 = 42;
161+
static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
162+
static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
163163
```
164164
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:
165+
Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However,
166+
the address can change when the program is linked, as well as change
167+
between different executions due to ASLR, and many linkers would
168+
not be able to calculate the value of `WHAT`.
169+
170+
On the other hand, static and constant pointers can point either to
171+
a known numeric address or to the address of a symbol.
167172
168173
```
169-
const X: u32 = 1;
170-
const Y: usize = &X as *const u32 as usize;
171-
println!("{}", Y);
174+
static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
175+
// ... and also
176+
static MY_STATIC_ADDR2: *const u32 = &MY_STATIC;
177+
178+
const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
172179
```
180+
181+
This does not pose a problem by itself because they can't be
182+
accessed directly.
173183
"##,
174184

175185
E0019: r##"
@@ -347,55 +357,59 @@ From [RFC 246]:
347357
[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
348358
"##,
349359

360+
350361
E0395: r##"
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:
362+
The value assigned to a constant scalar must be known at compile time,
363+
which is not the case when comparing raw pointers.
353364
365+
366+
Erroneous code example:
354367
```
355-
static foo: i32 = 42;
356-
static bar: i32 = 43;
368+
static FOO: i32 = 42;
369+
static BAR: i32 = 42;
357370
358-
static baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
371+
static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
359372
// error: raw pointers cannot be compared in statics!
360373
```
361374
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:
375+
The address assigned by the linker to `FOO` and `BAR` may or may not
376+
be identical, so the value of `BAZ` can't be determined.
377+
378+
If you want to do the comparison, please do it at run-time.
379+
380+
For example:
364381
365382
```
366-
static foo: i32 = 42;
367-
static bar: i32 = 43;
383+
static FOO: i32 = 42;
384+
static BAR: i32 = 42;
368385
369-
let baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
386+
let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
370387
// baz isn't a constant expression so it's ok
371388
```
372389
"##,
373390

374391
E0396: r##"
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
377-
example:
392+
The value behind a raw pointer can't be determined at compile-time
393+
(or even link-time), which means it can't be used in a constant
394+
expression.
378395
396+
For example:
379397
```
380-
const foo: i32 = 42;
381-
const baz: *const i32 = (&foo as *const i32);
398+
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
382399
383-
const deref: i32 = *baz;
400+
const VALUE: u8 = unsafe { *REG_ADDR };
384401
// error: raw pointers cannot be dereferenced in constants
385402
```
386403
387-
To fix this error, please do not assign this value to a constant expression.
388-
Example:
404+
A possible fix is to dereference your pointer at some point in run-time.
389405
390-
```
391-
const foo: i32 = 42;
392-
const baz: *const i32 = (&foo as *const i32);
406+
For example:
393407
394-
unsafe { let deref: i32 = *baz; }
395-
// baz isn't a constant expression so it's ok
396408
```
409+
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
397410
398-
You'll also note that this assignment must be done in an unsafe block!
411+
let reg_value = unsafe { *REG_ADDR };
412+
```
399413
"##,
400414

401415
E0397: r##"

0 commit comments

Comments
 (0)