Skip to content

Commit 2bf1c68

Browse files
authored
Tweak wording of non_exhaustive subtleties
1 parent 76b4016 commit 2bf1c68

File tree

1 file changed

+42
-5
lines changed

1 file changed

+42
-5
lines changed

text/0000-default-field-values.md

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,42 @@ let _ = Foo { .. }; // Currently forbidden
564564
Would be *allowed*, changing the meaning of this code in a way that goes against
565565
user intention.
566566

567+
Some alternatives present for the case mentioned above can be:
568+
569+
- Add a private non-defaulted field:
570+
```rust
571+
#[non_exhaustive]
572+
pub struct Config {
573+
pub width: u16 = 640,
574+
pub height: u16 = 480,
575+
__priv: PhantomData<()>
576+
}
577+
```
578+
which disallows the following
579+
```rust
580+
let _ = Config { .. };
581+
let _ = Config { width: 800, height: 600, .. };
582+
```
583+
at the cost of forcing the API-internal construction of `Config` to specify `__priv`
584+
everywhere.
585+
- If defaulting private fields is allowed outside of the current crate, or that behavior
586+
can be explicitly set by the user, then the following:
587+
```rust
588+
#[non_exhaustive]
589+
pub struct Config {
590+
pub width: u16 = 640,
591+
pub height: u16 = 480,
592+
__priv: PhantomData<()> = PhantomData,
593+
}
594+
```
595+
still disallows the following
596+
```rust
597+
let _ = Config { .. };
598+
let _ = Config { width: 800, height: 600, .. };
599+
```
600+
while also allowing precisely that syntax within the API-internal constructions of
601+
`Config`.
602+
567603
## Defaults for `enum`s
568604

569605
The ability to give fields default values is not limited to `struct`s.
@@ -1552,7 +1588,9 @@ this RFC so that constructor functions are regained if so desired.
15521588

15531589
As an alternative, users who desire the semantics described above can
15541590
omit `#[non_exhaustive]` from their type and instead add a private
1555-
defaulted field that has a ZST.
1591+
defaulted field that has a ZST, if the construction of structs with
1592+
private fields is allowed. If they are not, then the attribute is still
1593+
relevant and needed to control the accepted code to force `..`.
15561594

15571595
## `enum` variants
15581596

@@ -1619,7 +1657,6 @@ let _ = Foo { .. }; // Currently forbidden
16191657

16201658
[RFC-0736]: https://github.com/rust-lang/rfcs/blob/master/text/0736-privacy-respecting-fru.md
16211659

1622-
16231660
In this RFC we do not propose any changes to the normal visibility rules:
16241661
constructing a `struct` with default fields requires those fields to be visible
16251662
in that scope.
@@ -1659,8 +1696,8 @@ This used to be the behavior the Functional Record Update syntax had *before*
16591696
private fields with values from a base expression.
16601697

16611698
If a user wishes to keep other modules from constructing a `Foo` with
1662-
`Foo { .. }` they can simply add, or keep, one private field without a default
1663-
or add `#[non_exhaustive]`, as mising these two features is not allowed under
1699+
`Foo { .. }` they can add, or keep, one private field without a default, or add
1700+
(for now) `#[non_exhaustive]`, as mixing these two features is not allowed under
16641701
this RFC. Situations where this can be important include those where `Foo` is
16651702
some token for some resource and where fabricating a `Foo` may prove dangerous
16661703
or worse unsound. This is however no different than carelessly adding
@@ -1679,7 +1716,7 @@ such as an attribute or item modifier:
16791716

16801717
```rust
16811718
pub mod foo {
1682-
#[allow_private_defaults]
1719+
#[allow_private_defaults(gamma)]
16831720
pub struct Alpha {
16841721
beta: u8 = 42,
16851722
gamma: bool = true,

0 commit comments

Comments
 (0)