Skip to content

Necromancing (putting back some removed error codes explanations) #66836

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

Closed
wants to merge 8 commits into from
9 changes: 8 additions & 1 deletion src/librustc_error_codes/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,25 @@
register_diagnostics! {
E0001: include_str!("./error_codes/E0001.md"),
E0002: include_str!("./error_codes/E0002.md"),
E0003: include_str!("./error_codes/E0003.md"),
E0004: include_str!("./error_codes/E0004.md"),
E0005: include_str!("./error_codes/E0005.md"),
E0007: include_str!("./error_codes/E0007.md"),
E0008: include_str!("./error_codes/E0008.md"),
E0009: include_str!("./error_codes/E0009.md"),
E0010: include_str!("./error_codes/E0010.md"),
E0011: include_str!("./error_codes/E0011.md"),
E0013: include_str!("./error_codes/E0013.md"),
E0014: include_str!("./error_codes/E0014.md"),
E0015: include_str!("./error_codes/E0015.md"),
E0016: include_str!("./error_codes/E0016.md"),
E0017: include_str!("./error_codes/E0017.md"),
E0018: include_str!("./error_codes/E0018.md"),
E0019: include_str!("./error_codes/E0019.md"),
E0020: include_str!("./error_codes/E0020.md"),
E0022: include_str!("./error_codes/E0022.md"),
E0023: include_str!("./error_codes/E0023.md"),
E0024: include_str!("./error_codes/E0024.md"),
E0025: include_str!("./error_codes/E0025.md"),
E0026: include_str!("./error_codes/E0026.md"),
E0027: include_str!("./error_codes/E0027.md"),
Expand Down Expand Up @@ -412,7 +420,6 @@ E0744: include_str!("./error_codes/E0744.md"),
E0745: include_str!("./error_codes/E0745.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
// E0035, merged into E0087/E0089
// E0036, merged into E0087/E0089
// E0068,
Expand Down
15 changes: 15 additions & 0 deletions src/librustc_error_codes/error_codes/E0003.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#### Note: this error code is no longer emitted by the compiler.

Not-a-Number (NaN) values cannot be compared for equality and hence can never
match the input to a match expression. To match against NaN values, you should
instead use the `is_nan()` method in a guard, like so:

```
let number = 0f64;

match number {
// ...
x if x.is_nan() => { /* ... */ }
x => { /* ... */ }
}
```
73 changes: 73 additions & 0 deletions src/librustc_error_codes/error_codes/E0008.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#### Note: this error code is no longer emitted by the compiler.

Names bound in match arms retain their type in pattern guards. As such, if a
name is bound by move in a pattern, it should also be moved to wherever it is
referenced in the pattern guard code. Doing so however would prevent the name
from being available in the body of the match arm. Consider the following:

```
match Some("hi".to_string()) {
Some(s) if s.len() == 0 => {}, // use s.
_ => {},
}
```

The variable `s` has type `String`, and its use in the guard is as a variable of
type `String`. The guard code effectively executes in a separate scope to the
body of the arm, so the value would be moved into this anonymous scope and
therefore becomes unavailable in the body of the arm.
The problem above can be solved by using the `ref` keyword.

```
match Some("hi".to_string()) {
Some(ref s) if s.len() == 0 => {},
_ => {},
}
```

Though this example seems innocuous and easy to solve, the problem becomes clear
when it encounters functions which consume the value:

```compile_fail,E0507
struct A {}

impl A {
fn consume(self) -> usize {
0
}
}

fn main() {
let a = Some(A{});
match a {
Some(y) if y.consume() > 0 => {}
_ => {}
}
}
```

In this situation, even the `ref` keyword cannot solve it, since borrowed
content cannot be moved. This problem cannot be solved generally. If the value
can be cloned, here is a not-so-specific solution:

```
#[derive(Clone)]
struct A {}

impl A {
fn consume(self) -> usize {
0
}
}

fn main() {
let a = Some(A{});
match a{
Some(ref y) if y.clone().consume() > 0 => {}
_ => {}
}
}
```

If the value will be consumed in the pattern guard, using its clone will not
move its ownership, so the code works.
30 changes: 30 additions & 0 deletions src/librustc_error_codes/error_codes/E0011.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#### Note: this error code is no longer emitted by the compiler.

Using a user-defined operator on const/static variable is restricted to what
can be evaluated at compile-time. Using an user-defined operator could call a
user-defined function, which is not allowed.

Bad example:

```compile_fail,E0015
use std::ops::Index;

struct Foo { a: u8 }

impl ::std::ops::Index<u8> for Foo {
type Output = u8;
fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
}

const a: Foo = Foo { a: 0u8 };
const b: u8 = a[0]; // Index trait is defined by the user, bad!
```

Only operators on builtin types are allowed.

Example:

```
const a: &'static [i32] = &[1, 2, 3];
const b: i32 = a[0]; // Good!
```
14 changes: 14 additions & 0 deletions src/librustc_error_codes/error_codes/E0016.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#### Note: this error code is no longer emitted by the compiler.

Blocks in constants may only contain items (such as constant, function
definition, etc...) and a tail expression. Erroneous code example:

```
const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
```

To avoid it, you have to replace the non-item object:

```
const FOO: i32 = { const X : i32 = 0; X };
```
29 changes: 29 additions & 0 deletions src/librustc_error_codes/error_codes/E0018.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#### Note: this error code is no longer emitted by the compiler.

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:

```compile_fail,E0658
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;
```

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.

```
static MY_STATIC: u32 = 42;
static MY_STATIC_ADDR: &'static 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.
12 changes: 12 additions & 0 deletions src/librustc_error_codes/error_codes/E0020.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#### Note: this error code is no longer emitted by the compiler.

This error indicates that an attempt was made to divide by zero (or take the
remainder of a zero divisor) in a static or constant expression. Erroneous
code example:

```compile_fail
#[deny(const_err)]

const X: i32 = 42 / 0;
// error: attempt to divide by zero in a constant expression
```
17 changes: 17 additions & 0 deletions src/librustc_error_codes/error_codes/E0022.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#### Note: this error code is no longer emitted by the compiler.

Constant functions are not allowed to mutate anything. Thus, binding to an
argument with a mutable pattern is not allowed. For example,

```
const fn foo(mut x: u8) {
// do stuff
}
```

Is incorrect because the function body may not mutate `x`.

Remove any mutable bindings from the argument list to fix this error. In case
you need to mutate the argument, try lazily initializing a global variable
instead of using a `const fn`, or refactoring the code to a functional style to
avoid mutation if possible.
24 changes: 24 additions & 0 deletions src/librustc_error_codes/error_codes/E0024.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#### Note: this error code is no longer emitted by the compiler.

This error indicates that a pattern attempted to extract the fields of an enum
variant with no fields. Here's a tiny example of this error:

```compile_fail,E0532
// This enum has two variants.
enum Number {
// This variant has no fields.
Zero,
// This variant has one field.
One(u32)
}

// Assuming x is a Number we can pattern match on its contents.
match Number::Zero {
Number::Zero(inside) => {}
Number::One(inside) => {}
}
```

The pattern match `Zero(inside)` is incorrect because the `Zero` variant
contains no fields, yet the `inside` name attempts to bind the first field of
the enum.