Auto merge of #24975 - michaelsproul:enum-diagnostics, r=pnkfelix
Explanations for E0079, E0080, E0081, E0082, E0083 and E0084 as part of #24407. All the errors concern the use of `#[repr(X)]` with enum types. I also updated the short description for E0079 so that it takes sign into account.
This commit is contained in:
commit
e962870420
3 changed files with 107 additions and 7 deletions
|
@ -227,6 +227,31 @@ 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.
|
||||
"##,
|
||||
|
||||
E0079: r##"
|
||||
Enum variants which contain no data can be given a custom integer
|
||||
representation. This error indicates that the value provided is not an
|
||||
integer literal and is therefore invalid.
|
||||
"##,
|
||||
|
||||
E0080: r##"
|
||||
This error indicates that the compiler was unable to sensibly evaluate an
|
||||
integer expression provided as an enum discriminant. Attempting to divide by 0
|
||||
or causing integer overflow are two ways to induce this error. For example:
|
||||
|
||||
```
|
||||
enum Enum {
|
||||
X = (1 << 500),
|
||||
Y = (1 / 0)
|
||||
}
|
||||
```
|
||||
|
||||
Ensure that the expressions given can be evaluated as the desired integer type.
|
||||
See the FFI section of the Reference for more information about using a custom
|
||||
integer type:
|
||||
|
||||
http://doc.rust-lang.org/reference.html#ffi-attributes
|
||||
"##,
|
||||
|
||||
E0133: r##"
|
||||
Using unsafe functionality, such as dereferencing raw pointers and calling
|
||||
functions via FFI or marked as unsafe, is potentially dangerous and disallowed
|
||||
|
@ -507,8 +532,6 @@ register_diagnostics! {
|
|||
E0017,
|
||||
E0019,
|
||||
E0022,
|
||||
E0079, // enum variant: expected signed integer constant
|
||||
E0080, // enum variant: constant evaluation error
|
||||
E0109,
|
||||
E0110,
|
||||
E0134,
|
||||
|
|
|
@ -5732,8 +5732,10 @@ fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>,
|
|||
Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
|
||||
Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
|
||||
Ok(_) => {
|
||||
let sign_desc = if repr_type.is_signed() { "signed" } else { "unsigned" };
|
||||
span_err!(cx.sess, e.span, E0079,
|
||||
"expected signed integer constant");
|
||||
"expected {} integer constant",
|
||||
sign_desc);
|
||||
current_disr_val = attempt_fresh_value();
|
||||
}
|
||||
Err(ref err) => {
|
||||
|
|
|
@ -10,6 +10,85 @@
|
|||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
register_long_diagnostics! {
|
||||
|
||||
E0081: r##"
|
||||
Enum discriminants are used to differentiate enum variants stored in memory.
|
||||
This error indicates that the same value was used for two or more variants,
|
||||
making them impossible to tell apart.
|
||||
|
||||
```
|
||||
// Good.
|
||||
enum Enum {
|
||||
P,
|
||||
X = 3,
|
||||
Y = 5
|
||||
}
|
||||
|
||||
// Bad.
|
||||
enum Enum {
|
||||
P = 3,
|
||||
X = 3,
|
||||
Y = 5
|
||||
}
|
||||
```
|
||||
|
||||
Note that variants without a manually specified discriminant are numbered from
|
||||
top to bottom starting from 0, so clashes can occur with seemingly unrelated
|
||||
variants.
|
||||
|
||||
```
|
||||
enum Bad {
|
||||
X,
|
||||
Y = 0
|
||||
}
|
||||
```
|
||||
|
||||
Here `X` will have already been assigned the discriminant 0 by the time `Y` is
|
||||
encountered, so a conflict occurs.
|
||||
"##,
|
||||
|
||||
E0082: r##"
|
||||
The default type for enum discriminants is `isize`, but it can be adjusted by
|
||||
adding the `repr` attribute to the enum declaration. This error indicates that
|
||||
an integer literal given as a discriminant is not a member of the discriminant
|
||||
type. For example:
|
||||
|
||||
```
|
||||
#[repr(u8)]
|
||||
enum Thing {
|
||||
A = 1024,
|
||||
B = 5
|
||||
}
|
||||
```
|
||||
|
||||
Here, 1024 lies outside the valid range for `u8`, so the discriminant for `A` is
|
||||
invalid. You may want to change representation types to fix this, or else change
|
||||
invalid discriminant values so that they fit within the existing type.
|
||||
|
||||
Note also that without a representation manually defined, the compiler will
|
||||
optimize by using the smallest integer type possible.
|
||||
"##,
|
||||
|
||||
E0083: r##"
|
||||
At present, it's not possible to define a custom representation for an enum with
|
||||
a single variant. As a workaround you can add a `Dummy` variant.
|
||||
|
||||
See: https://github.com/rust-lang/rust/issues/10292
|
||||
"##,
|
||||
|
||||
E0084: r##"
|
||||
It is impossible to define an integer type to be used to represent zero-variant
|
||||
enum values because there are no zero-variant enum values. There is no way to
|
||||
construct an instance of the following type using only safe code:
|
||||
|
||||
```
|
||||
enum Empty {}
|
||||
```
|
||||
"##
|
||||
|
||||
}
|
||||
|
||||
register_diagnostics! {
|
||||
E0023,
|
||||
E0024,
|
||||
|
@ -51,10 +130,6 @@ register_diagnostics! {
|
|||
E0075,
|
||||
E0076,
|
||||
E0077,
|
||||
E0081,
|
||||
E0082,
|
||||
E0083,
|
||||
E0084,
|
||||
E0085,
|
||||
E0086,
|
||||
E0087,
|
||||
|
|
Loading…
Reference in a new issue