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

1.66 blog: clarify enum discriminant section #1056

Merged
merged 1 commit into from
Dec 15, 2022
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
13 changes: 3 additions & 10 deletions posts/2022-12-15-Rust-1.66.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,13 @@ enum Bar {
A,
B,
C = 42,
D,
}
```

Here the `Bar` enum is guaranteed to have the same layout as `u8`. Each variant will use either the specified discriminant value or default to starting with 0.
Here the `Bar` enum is guaranteed to have the same layout as `u8`. In addition, the `Bar::C` variant is guaranteed to have a discriminant of 42. Variants without explicitly-specified values will have discriminants that are automatically assigned according to their order in the source code, so `Bar::A` will have a discriminant of 0, `Bar::B` will have a discriminant of 1, and `Bar::D` will have a discriminant of 43. Without this feature, the only way to set the explicit value of `Bar::C` would be to add 41 unnecessary variants before it!

```rust
assert_eq!(0, Bar::A as u8);
assert_eq!(1, Bar::B as u8);
assert_eq!(42, Bar::C as u8);
```

You could even add fields to enums with `#[repr(Int)]`, and they would be laid out in a predictable way. Previously, however, you could not use these features together. That meant that making `Foo::C`'s discriminant equal to 42 as above would be harder to achieve. You would need to add 41 hidden variants in between as a workaround with implicit discriminants!

Starting in Rust 1.66.0, the above example compiles, allowing you to use explicit discriminants on any enum with a `#[repr(Int)]` attribute.
Note: whereas for field-less enums it is possible to inspect a discriminant via `as` casting (e.g. `Bar::C as u8`), Rust provides no language-level way to access the raw discriminant of an enum with fields. Instead, currently unsafe code must be used to inspect the discriminant of an enum with fields. Since this feature is intended for use with cross-language FFI where unsafe code is already necessary, this should hopefully not be too much of an extra burden. In the meantime, if all you need is an opaque handle to the discriminant, please see the `std::mem::discriminant` function.

### `core::hint::black_box`

Expand Down