Skip to content

Improve the error explanations for check_const #30932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 24, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 50 additions & 36 deletions src/librustc_passes/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,26 +150,36 @@ If you really want global mutable state, try using `static mut` or a global
"##,

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,
example:
The value of static and constant integers must be known at compile time. You
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;
const Y: *const u32 = &X;
static MY_STATIC: u32 = 42;
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
in a non-constant integer which lead to this error. Example:
Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However,
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;
const Y: usize = &X as *const u32 as usize;
println!("{}", Y);
static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
// ... and also
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##"
Expand Down Expand Up @@ -347,55 +357,59 @@ From [RFC 246]:
[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
"##,


E0395: r##"
The value assigned to a constant expression must be known at compile time,
which is not the case when comparing raw pointers. Erroneous code example:
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:
```
static foo: i32 = 42;
static bar: i32 = 43;
static FOO: i32 = 42;
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!
```

Please check that the result of the comparison can be determined at compile time
or isn't assigned to a constant expression. Example:
The address assigned by the linker to `FOO` and `BAR` may or may not
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 bar: i32 = 43;
static FOO: i32 = 42;
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
```
"##,

E0396: r##"
The value assigned to a constant expression must be known at compile time,
which is not the case when dereferencing raw pointers. Erroneous code
example:
The value behind a raw pointer can't be determined at compile-time
(or even link-time), which means it can't be used in a constant
expression.

For example:
```
const foo: i32 = 42;
const baz: *const i32 = (&foo as *const i32);
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;

const deref: i32 = *baz;
const VALUE: u8 = unsafe { *REG_ADDR };
// error: raw pointers cannot be dereferenced in constants
```

To fix this error, please do not assign this value to a constant expression.
Example:
A possible fix is to dereference your pointer at some point in run-time.

```
const foo: i32 = 42;
const baz: *const i32 = (&foo as *const i32);
For example:

unsafe { let deref: i32 = *baz; }
// baz isn't a constant expression so it's ok
```
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;

You'll also note that this assignment must be done in an unsafe block!
let reg_value = unsafe { *REG_ADDR };
```
"##,

E0397: r##"
Expand Down