Skip to content
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

Clarify the semantics of enum discriminants #31772

Merged
merged 1 commit into from
Mar 9, 2016
Merged
Show file tree
Hide file tree
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
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