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

Future-proofing enums/structs with #[non_exhaustive] attribute #2008

Merged
merged 11 commits into from
Aug 26, 2017
43 changes: 41 additions & 2 deletions text/0000-non-exhaustive.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@ as well.
# Detailed design

An attribute `#[non_exhaustive]` is added to the language, which will (for now)
fail to compile if it's used on anything other than an enum, struct definition,
or enum variant.
fail to compile if it's used on anything other than an enum or struct
definition, or enum variant.

## Enums

Expand Down Expand Up @@ -417,6 +417,10 @@ Then we the only valid way of matching will be:
let Config { 0: width, 1: height, .. } = config;
Copy link
Contributor

@petrochenkov petrochenkov Jun 14, 2017

Choose a reason for hiding this comment

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

Again, FRU expressions should be legal here as well.

```

We can think of this as lowering the visibility of the constructor to
`pub(crate)` if it is marked as `pub`, then applying the standard structure
rules.
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to apply to unit structs as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do; one sec.


## Unit structs

Unit structs will work very similarly to tuple structs. Consider this struct:
Expand All @@ -433,6 +437,41 @@ match it like:
let Unit { .. } = unit;
Copy link
Contributor

@petrochenkov petrochenkov Jun 14, 2017

Choose a reason for hiding this comment

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

Same as previously, the constructor's visibility need to be adjusted and FRU is usable.

```

To users of this crate, this will act exactly as if the struct were defined as:

```
#[non_exhaustive]
pub struct Unit {}
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 seems to be equivalent to 3d56889#r135395315, but I'd still prefer to use the same wording for tuple and unit structs.

```

## Functional record updates

Functional record updates will operate exactly the same regardless of whether
structs are marked as non-exhaustive or not. For example, given this struct:
Copy link
Contributor

@petrochenkov petrochenkov Aug 26, 2017

Choose a reason for hiding this comment

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

Hm, the decision was the opposite - FRU is not permitted with non_exhaustive structs (in other crates).
FRU (with current rules) is a promise to not add private fields to a struct, and we want to be able to add private fields to non_exhaustive structs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought that FRU still worked when structs have private fields?

Copy link
Contributor

Choose a reason for hiding this comment

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

No :(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unless I'm misunderstanding, I tried this out on the playground and it seems to work: https://play.rust-lang.org/?gist=eabe36303f9da0ced44c237ca3b29d45&version=stable

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

…right, I'll update the RFC.


```
#[derive(Debug)]
#[non_exhaustive]
pub struct Config {
pub width: u16,
pub height: u16,
pub fullscreen: bool,
}
impl Default for Config {
fn default() -> Config {
Config { width: 640, height: 480, fullscreen: false }
}
}
```

The below code will print `Config { width: 1920, height: 1080, fullscreen:
false }` regardless of which crate is calling it:

```
let c = Config { width: 1920, height: 1080, ..Config::default() };
println!("{:?}", c);
```

## Changes to rustdoc

Right now, the only indicator that rustdoc gives for non-exhaustive enums and
Expand Down