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

Update documentation for arbitrary_enum_discriminant feature #1055

Merged
merged 9 commits into from
Jan 8, 2023

Conversation

fee1-dead
Copy link
Member

Continuation of #639. This should only be merged after the feature is stabilized.

@ehuss ehuss added the S-waiting-on-stabilization Waiting for a stabilization PR to be merged in the main Rust repository label Jul 4, 2021
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 18, 2021
Stabilize `arbitrary_enum_discriminant`

Closes rust-lang#60553.

----

## Stabilization Report

_copied from rust-lang#60553 (comment)

### Summary

Enables a user to specify *explicit* discriminants on arbitrary enums.

Previously, this was hard to achieve:

```rust
#[repr(u8)]
enum Foo {
    A(u8) = 0,
    B(i8) = 1,
    C(bool) = 42,
}
```

Someone would need to add 41 hidden variants in between as a workaround with implicit discriminants.

In conjunction with [RFC 2195](https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md), this feature would provide more flexibility for FFI and unsafe code involving enums.

### Test cases

Most tests are in [`src/test/ui/enum-discriminant`](https://github.com/rust-lang/rust/tree/master/src/test/ui/enum-discriminant), there are two [historical](https://github.com/rust-lang/rust/blob/master/src/test/ui/parser/tag-variant-disr-non-nullary.rs) [tests](https://github.com/rust-lang/rust/blob/master/src/test/ui/parser/issue-17383.rs) that are now covered by the feature (removed by this pr due to them being obsolete).

### Edge cases

The feature is well defined and does not have many edge cases.
One [edge case](rust-lang#70509) was related to another unstable feature named `repr128` and is resolved.

### Previous PRs

The [implementation PR](rust-lang#60732) added documentation to the Unstable Book, rust-lang/reference#1055 was opened as a continuation of rust-lang/reference#639.

### Resolution of unresolved questions

The questions are resolved in rust-lang#60553 (comment).

----

(someone please add `needs-fcp`)
Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks great! 🎉

There's another link in const_eval.md that references #custom-discriminant-values-for-fieldless-enumerations that needs to be updated.

src/items/enumerations.md Outdated Show resolved Hide resolved
<ol>
<li>

if the enumeration is "C-like" (i.e., it has no tuple or struct variants); e.g.:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if the enumeration is "C-like" (i.e., it has no tuple or struct variants); e.g.:
if the enumeration is fieldless (i.e., it has no tuple or struct variants); e.g.:

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong because the compiler would tell me to add a repr for the enum.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what this has to do with the representation. We have been moving the reference to use the term "fieldless enum" instead of "c-like"; that is the terminology we would prefer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but only c-like enums are allowed to have a discriminant without a #[repr()] attribute.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm still confused. The term "c-like enum" has historically been used for Rust enums that only has unit variants (that is, variants without fields). We have changed the terminology in the reference to use the phrase "fieldless enum" instead. We want to stop using the phrase "c-like" altogether. Indeed, this particular section is showing a fieldless enum. Why do you still want to use the term "c-like" here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I can see how the literal interpretation of "fieldless" could be confused with those. The two examples with brackets define tuple and struct variants, they just have 0 fields. The unit variant has a distinctly different meaning which has different semantics. As defined here in the reference, a "fieldless enum" is one with only unit variants (your first example).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that is correct. The reference says

An enum where no constructors contain fields are called a
field-less enum.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this PR is the one adding that definition, no? I guess my review could be more thorough here, but if you want to make that statement more precise, I would reword it to be that a fieldless enum is one that only has unit variants. I would also drop the hyphen. AFAIK, the language has always generally treated unit variants different from struct and tuple variants, even if the later two don't have fields.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all "fieldless" enums can be cast to their discriminant values. however only c-like enums may specify discriminants without a repr. @jswrenn has already said this on the original PR: #639 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened rust-lang/rust#88203. This should be made consistent and I see no problems for fieldless enums to have an unspecified repr.

src/items/enumerations.md Outdated Show resolved Hide resolved
@ehuss ehuss added S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. and removed S-waiting-on-stabilization Waiting for a stabilization PR to be merged in the main Rust repository labels Aug 19, 2021
@fee1-dead fee1-dead requested a review from ehuss August 19, 2021 07:20
@fee1-dead fee1-dead force-pushed the arbitrary_enum_discriminant branch from db8d5b0 to 2e93a1f Compare April 6, 2022 01:32
@fee1-dead
Copy link
Member Author

fee1-dead commented Apr 6, 2022

@rustbot label -S-waiting-on-author

@rustbot
Copy link
Collaborator

rustbot commented Apr 6, 2022

Error: The feature shortcut is not enabled in this repository.
To enable it add its section in the triagebot.toml in the root of the repository.

Please let @rust-lang/release know if you're having trouble with this bot.

@fee1-dead

This comment was marked as resolved.

@fee1-dead fee1-dead force-pushed the arbitrary_enum_discriminant branch from 2e93a1f to ccce6d9 Compare April 6, 2022 01:42
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 24, 2022
…ry_enum_discriminant, r=joshtriplett

Stabilize arbitrary_enum_discriminant, take 2

Documentation has been updated in rust-lang/reference#1055. cc rust-lang#86860 for previous stabilization report.

Not yet marks rust-lang#60553 as done: need documentation in the rust reference.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 24, 2022
…ry_enum_discriminant, r=joshtriplett

Stabilize arbitrary_enum_discriminant, take 2

Documentation has been updated in rust-lang/reference#1055. cc rust-lang#86860 for previous stabilization report.

Not yet marks rust-lang#60553 as done: need documentation in the rust reference.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 24, 2022
…ry_enum_discriminant, r=joshtriplett

Stabilize arbitrary_enum_discriminant, take 2

Documentation has been updated in rust-lang/reference#1055. cc rust-lang#86860 for previous stabilization report.

Not yet marks rust-lang#60553 as done: need documentation in the rust reference.
compiler-errors added a commit to compiler-errors/rust that referenced this pull request Oct 25, 2022
…ry_enum_discriminant, r=joshtriplett

Stabilize arbitrary_enum_discriminant, take 2

Documentation has been updated in rust-lang/reference#1055. cc rust-lang#86860 for previous stabilization report.

Not yet marks rust-lang#60553 as done: need documentation in the rust reference.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 26, 2022
…ry_enum_discriminant, r=joshtriplett

Stabilize arbitrary_enum_discriminant, take 2

Documentation has been updated in rust-lang/reference#1055. cc rust-lang#86860 for previous stabilization report.

Not yet marks rust-lang#60553 as done: need documentation in the rust reference.
Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning to this now that it has landed. I think the structure and content look great. I just want to nail down the details. Other than the comments I added, is this otherwise up to date with what eventually finalized?

following the variant name with `=` and a [constant expression]:


1. if the enumeration is "C-like" (i.e., it has no tuple or struct variants); e.g.:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we tried quite hard to scrub the presence of the "C-like" terminology, and this PR seems to bring it back. Would it be possible to come up with some other terminology here? Or, perhaps it doesn't need an explicit term, but could just say "if the enumeration only has Unit variants…"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, maybe we can use Unit-only and link to a section when referring to it somewhere else. Will do so in a moment.

Comment on lines 168 to 181
If an enumeration is C-like (with no tuple and struct variants), then its
discriminant can be directly accessed with a [numeric cast]; e.g.:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be missing the grandfathered support for casting enums with empty constructors, like:

enum Fieldless {
    Tuple(),
    Struct{},
    Unit,
}

assert_eq!(Fieldless::Tuple() as u8, 0);
assert_eq!(Fieldless::Struct{} as u8, 1);
assert_eq!(Fieldless::Unit as u8, 2);

Was that excluded for a reason?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that they cannot be casted to their discriminant if their discriminants are specified. This is summarized in rust-lang/rust#60553 (comment). This will likely need more discussion around the design, but none of the design concerns block the stabilization of arbitrary_enum_discriminant.

If you would like this to be included, then I can put that in.

Comment on lines 61 to 62
An enum where no constructors contain fields are called a
*<a id="field-less-enum">field-less enum</a>*.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the field-less term got a little confusing, and it's still not clear to me, does it also cover empty constructors, like:

enum Fieldless {
    Tuple(),
    Struct{},
    Unit,
}

If so, perhaps that needs to be made explicit?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I will add that as an example.


impl Enum {
fn discriminant(&self) -> u8 {
unsafe { *(self as *const Self as *const u8) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right to me? Just because it's repr(u8) I don't think that means that the discriminant is necessarily first.

If the enum were repr(C) or repr(C, u8) then it'd be ok because the field order would be specified. But for repr(Rust) I'm pretty sure we're allowed to put the discriminant after the payload, if we wanted to.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, never mind, it looks like https://rust-lang.github.io/rfcs/2195-really-tagged-unions.html#guide-level-explanation means that repr(u8) disables all field reordering too, not just sets the discriminant size :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that odd, too. The RFC justifies this by saying the discriminant position needs to be deterministic, which seems possible to do without disabling other field reordering?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(At this point it seems too late to change, but an edition change could require repr(C) for deterministic field ordering.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would need another flag to distinguish between the union-of-structs and struct-containing-union-of-structs layouts, though. Which might be nice, though!

I suppose the argument is that the size of the discriminant can't matter to safe code, so the only point of ever specifying its width is to get deterministic layout?

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 27, 2022
Explain how to get the discriminant out of a `#[repr(T)] enum` with payload

example stolen from rust-lang/reference#1055

`@rustbot` label A-docs
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 27, 2022
Explain how to get the discriminant out of a `#[repr(T)] enum` with payload

example stolen from rust-lang/reference#1055

``@rustbot`` label A-docs
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 27, 2022
Explain how to get the discriminant out of a `#[repr(T)] enum` with payload

example stolen from rust-lang/reference#1055

```@rustbot``` label A-docs
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 27, 2022
Explain how to get the discriminant out of a `#[repr(T)] enum` with payload

example stolen from rust-lang/reference#1055

````@rustbot```` label A-docs
@fee1-dead
Copy link
Member Author

@rustbot ready

@rustbot
Copy link
Collaborator

rustbot commented Nov 28, 2022

Error: The feature shortcut is not enabled in this repository.
To enable it add its section in the triagebot.toml in the root of the repository.

Please file an issue on GitHub at triagebot if there's a problem with this bot, or reach out on #t-infra on Zulip.

@fee1-dead
Copy link
Member Author

@rustbot label -S-waiting-on-author +S-waiting-on-review

@rustbot rustbot added S-waiting-on-review Status: The marked PR is awaiting review from the PR author. and removed S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. labels Nov 28, 2022
The field-less casting was grandfathered in when arbitrary_enum_discriminant
was stabilized. It probably shouldn't be allowed.
The reference only uses uppercase for the first letter.
Although both work, semantically an `<a>` without an `href` is intended
to be a placeholder for a link.
This fixes some broken links.
Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and pushed some edits to fix some issues, but also to add the grandfathered behavior of allowing as casting for fieldless enums. If anyone feels that it should be different, feel free to open a PR.

@ehuss ehuss merged commit cc07ac0 into rust-lang:master Jan 8, 2023
@ehuss
Copy link
Contributor

ehuss commented Jan 8, 2023

Thanks again fee1-dead, and sorry for the super long delay.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 16, 2023
Update books

## rust-lang/book

1 commits in 2bd5d42c9956369132228da6409f0e68da56c51a..2cd1b5593d26dc6a03c20f8619187ad4b2485552
2023-01-12 14:47:47 UTC to 2023-01-12 14:47:47 UTC

- Typo (rust-lang/book#3457)

## rust-lang/nomicon

2 commits in 8ca261268068d80c0969260fff15199bad87b587..960d610e7f33889a2577f5f17c26f0d5c82b30df
2023-01-06 11:51:41 UTC to 2023-01-05 10:20:31 UTC

- vec/raw: Simplify `RawVec::grow` (rust-lang/nomicon#392)
- borrow-splitting: Use `take` instead of `replace` (rust-lang/nomicon#391)

## rust-lang/reference

4 commits in 3ae62681ff236d5528ef7c8c28ba7c6b2ecc6731..2cb0ed9ba56360949f492f9866afe8c293f9f9da
2023-01-13 03:16:35 UTC to 2023-01-07 00:08:06 UTC

- Update field-expr.md (rust-lang/reference#1318)
- Update documentation for arbitrary_enum_discriminant feature (rust-lang/reference#1055)
- Add links to definitions of terminology ... (rust-lang/reference#1315)
- Enable triagebot shortcuts (rust-lang/reference#1314)

## rust-lang/rust-by-example

2 commits in 8888f9428fe9a48f31de6bd2cef9b9bf80791edc..a9fb7d13eadfcc5f457962731f105b97f9a7474a
2023-01-14 10:25:39 UTC to 2023-01-11 18:25:42 UTC

- get_or_insert example: print my_fruit as intended (rust-lang/rust-by-example#1664)
- Update print.md (rust-lang/rust-by-example#1663)

## rust-lang/rustc-dev-guide

8 commits in b3e2a6e6c8a3aae5b5d950c63046f23bae07096d..7352353ae91c48b136d2ca7d03822e1448165e1e
2023-01-14 20:34:23 UTC to 2023-01-02 23:35:09 UTC

- fix examples for rustc 1.68.0-nightly (935dc07 2022-12-19) (rust-lang#1556) (rust-lang/rustc-dev-guide#1557)
- Update incremental-compilation-in-detail.md (rust-lang/rustc-dev-guide#1553)
- Link to the youtube recording of my talk, not the summary (rust-lang/rustc-dev-guide#1554)
- Change `src/test` to `tests` (rust-lang/rustc-dev-guide#1547)
- add full name for ICE (rust-lang/rustc-dev-guide#1552)
- Fix incorrect links (rust-lang/rustc-dev-guide#1549)
- fix rebase link (rust-lang/rustc-dev-guide#1546)
- Add a section for how to review code more easily (rust-lang/rustc-dev-guide#1538)
thomcc pushed a commit to tcdi/postgrestd that referenced this pull request Feb 10, 2023
Explain how to get the discriminant out of a `#[repr(T)] enum` with payload

example stolen from rust-lang/reference#1055

````@rustbot```` label A-docs
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Mar 21, 2023
…strieb

Update links for custom discriminants.

The discriminant documentation was updated in rust-lang/reference#1055 which changed the layout a bit. This updates the links to the updated locations.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Mar 22, 2023
…strieb

Update links for custom discriminants.

The discriminant documentation was updated in rust-lang/reference#1055 which changed the layout a bit. This updates the links to the updated locations.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Mar 22, 2023
…strieb

Update links for custom discriminants.

The discriminant documentation was updated in rust-lang/reference#1055 which changed the layout a bit. This updates the links to the updated locations.
oli-obk pushed a commit to oli-obk/miri that referenced this pull request Mar 23, 2023
Update links for custom discriminants.

The discriminant documentation was updated in rust-lang/reference#1055 which changed the layout a bit. This updates the links to the updated locations.
@fee1-dead fee1-dead deleted the arbitrary_enum_discriminant branch March 20, 2024 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: The marked PR is awaiting review from the PR author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants