Skip to content

Commit

Permalink
Clarify the semantics of enum discriminants
Browse files Browse the repository at this point in the history
  • Loading branch information
nodakai committed Mar 6, 2016
1 parent 21fb3ce commit 969d027
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
12 changes: 9 additions & 3 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1191,18 +1191,24 @@ a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 };
In this example, `Cat` is a _struct-like enum variant_,
whereas `Dog` is simply called an enum variant.

Enums have a discriminant. You can assign them explicitly:
Each enum value has a _discriminant_ which is an integer associated to it. You
can specify it explicitly:

```
enum Foo {
Bar = 123,
}
```

If a discriminant isn't assigned, they start at zero, and add one for each
The right hand side of the specification is interpreted as an `isize` value,
but the compiler is allowed to use a smaller type in the actual memory layout.
The [`repr` attribute](#ffi-attributes) can be added in order to change
the type of the right hand side and specify the memory layout.

If a discriminant isn't specified, they start at zero, and add one for each
variant, in order.

You can cast an enum to get this value:
You can cast an enum to get its discriminant:

```
# enum Foo { Bar = 123 }
Expand Down
27 changes: 18 additions & 9 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1133,15 +1133,16 @@ enum Bad {
}
```
Here `X` will have already been assigned the discriminant 0 by the time `Y` is
Here `X` will have already been specified 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:
When you specify enum discriminants with `=`, the compiler expects `isize`
values by default. Or you can add the `repr` attibute to the enum declaration
for an explicit choice of the discriminant type. In either cases, the
discriminant values must fall within a valid range for the expected type;
otherwise this error is raised. For example:
```compile_fail
#[repr(u8)]
Expand All @@ -1152,11 +1153,19 @@ enum Thing {
```
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.
invalid. Here is another, more subtle example which depends on target word size:
Note also that without a representation manually defined, the compiler will
optimize by using the smallest integer type possible.
```compile_fail
enum DependsOnPointerSize {
A = 1 << 32
}
```
Here, `1 << 32` is interpreted as an `isize` value. So it is invalid for 32 bit
target (`target_pointer_width = "32"`) but valid for 64 bit target.
You may want to change representation types to fix this, or else change invalid
discriminant values so that they fit within the existing type.
"##,

E0084: r##"
Expand Down

0 comments on commit 969d027

Please sign in to comment.