|  | 
|  | 1 | +# Summary | 
|  | 2 | + | 
|  | 3 | +This is an RFC to make all struct fields private by default. This includes both | 
|  | 4 | +tuple structs and structural structs. | 
|  | 5 | + | 
|  | 6 | +# Motivation | 
|  | 7 | + | 
|  | 8 | +Reasons for default private visibility | 
|  | 9 | + | 
|  | 10 | +* Visibility is often how soundness is achieved for many types in rust. These | 
|  | 11 | +  types are normally wrapping unsafe behavior of an FFI type or some other | 
|  | 12 | +  rust-specific behavior under the hood (such as the standard `Vec` type). | 
|  | 13 | +  Requiring these types to opt-in to being sound is unfortunate. | 
|  | 14 | + | 
|  | 15 | +* Forcing tuple struct fields to have non-overridable public visibility greatly | 
|  | 16 | +  reduces the utility of such types. Tuple structs cannot be used to create | 
|  | 17 | +  abstraction barriers as they can always be easily destructed. | 
|  | 18 | + | 
|  | 19 | +* Private-by-default is more consistent with the rest of the Rust language. All | 
|  | 20 | +  other aspects of privacy are private-by-default except for enum variants. Enum | 
|  | 21 | +  variants, however, are a special case in that they are inserted into the | 
|  | 22 | +  parent namespace, and hence naturally inherit privacy. | 
|  | 23 | + | 
|  | 24 | +* Public fields of a `struct` must be considered as part of the API of the type. | 
|  | 25 | +  This means that the exact definition of all structs is *by default* the API of | 
|  | 26 | +  the type. Structs must opt-out of this behavior if the `priv` keyword is | 
|  | 27 | +  required. By requiring the `pub` keyword, structs must opt-in to exposing more | 
|  | 28 | +  surface area to their API. | 
|  | 29 | + | 
|  | 30 | +Reasons for inherited visibility (today's design) | 
|  | 31 | + | 
|  | 32 | +* Public definitions like `pub struct Point { x: int, y: int }` are concise and | 
|  | 33 | +  easy to read. | 
|  | 34 | +* Private definitions certainly want private fields (to hide implementation | 
|  | 35 | +  details). | 
|  | 36 | + | 
|  | 37 | +# Detailed design | 
|  | 38 | + | 
|  | 39 | +Currently, rustc has two policies for dealing with the privacy of struct fields: | 
|  | 40 | + | 
|  | 41 | +* Tuple structs have public fields by default (including "newtype structs") | 
|  | 42 | +* Fields of structural structs (`struct Foo { ... }`) inherit the same privacy | 
|  | 43 | +  of the enclosing struct. | 
|  | 44 | + | 
|  | 45 | +This RFC is a proposal to unify the privacy of struct fields with the rest of | 
|  | 46 | +the language by making them private by default. This means that both tuple | 
|  | 47 | +variants and structural variants of structs would have private fields by | 
|  | 48 | +default. For example, the program below is accepted today, but would be rejected | 
|  | 49 | +with this RFC. | 
|  | 50 | + | 
|  | 51 | +```rust | 
|  | 52 | +mod inner { | 
|  | 53 | +    pub struct Foo(u64); | 
|  | 54 | +    pub struct Bar { field: u64 } | 
|  | 55 | +} | 
|  | 56 | + | 
|  | 57 | +fn main() { | 
|  | 58 | +    inner::Foo(10); | 
|  | 59 | +    inner::Bar { field: 10 }; | 
|  | 60 | +} | 
|  | 61 | +``` | 
|  | 62 | + | 
|  | 63 | +### Refinements to structural structs | 
|  | 64 | + | 
|  | 65 | +Public fields are quite a useful feature of the language, so syntax is required | 
|  | 66 | +to opt out of the private-by-default semantics. Structural structs already allow | 
|  | 67 | +visibility qualifiers on fields, and the `pub` qualifier would make the field | 
|  | 68 | +public instead of private. | 
|  | 69 | + | 
|  | 70 | +Additionally, the `priv` visibility will no longer be allowed to modify struct | 
|  | 71 | +fields. Similarly to how a `priv fn` is a compiler error, a `priv` field will | 
|  | 72 | +become a compiler error. | 
|  | 73 | + | 
|  | 74 | +### Refinements on tuple structs | 
|  | 75 | + | 
|  | 76 | +As with their structural cousins, it's useful to have tuple structs with public | 
|  | 77 | +fields. This RFC will modify the tuple struct grammar to: | 
|  | 78 | + | 
|  | 79 | +```ebnf | 
|  | 80 | +tuple_struct := 'struct' ident '(' fields ')' ';' | 
|  | 81 | +fields := field | field ',' fields | 
|  | 82 | +field := type | visibility type | 
|  | 83 | +``` | 
|  | 84 | + | 
|  | 85 | +For example, these definitions will be added to the language: | 
|  | 86 | + | 
|  | 87 | +```rust | 
|  | 88 | +// a "newtype wrapper" struct with a private field | 
|  | 89 | +struct Foo(u64); | 
|  | 90 | + | 
|  | 91 | +// a "newtype wrapper" struct with a public field | 
|  | 92 | +struct Bar(pub u64); | 
|  | 93 | + | 
|  | 94 | +// a tuple struct with many fields, only the first and last of which are public | 
|  | 95 | +struct Baz(pub u64, u32, f32, pub int); | 
|  | 96 | +``` | 
|  | 97 | + | 
|  | 98 | +Public fields on tuple structs will maintain the semantics that they currently | 
|  | 99 | +have today. The structs can be constructed, destructed, and participate in | 
|  | 100 | +pattern matches. | 
|  | 101 | + | 
|  | 102 | +Private fields on tuple structs will prevent the following behaviors: | 
|  | 103 | + | 
|  | 104 | +* Private fields cannot be bound in patterns (both in irrefutable and refutable | 
|  | 105 | +  contexts, i.e. `let` and `match` statements). | 
|  | 106 | +* Private fields cannot be specified outside of the defining module when | 
|  | 107 | +  constructing a tuple struct. | 
|  | 108 | + | 
|  | 109 | +These semantics are intended to closely mirror the behavior of private fields | 
|  | 110 | +for structural structs. | 
|  | 111 | + | 
|  | 112 | +### Statistics gathered | 
|  | 113 | + | 
|  | 114 | +A brief survey was performed over the entire `mozilla/rust` repository to gather | 
|  | 115 | +these statistics. While not representative of all projects, this repository | 
|  | 116 | +should give a good indication of what most structs look like in the real world. | 
|  | 117 | +The repository has both libraries (`libstd`) as well as libraries which don't | 
|  | 118 | +care much about privacy (`librustc`). | 
|  | 119 | + | 
|  | 120 | +These numbers tally up all structs from all locations, and only take into | 
|  | 121 | +account structural structs, not tuple structs. | 
|  | 122 | + | 
|  | 123 | +|                       | Inherited privacy | Private-by-default | | 
|  | 124 | +|-----------------------|------------------:|-------------------:| | 
|  | 125 | +| Private fields        |              1418 |               1852 | | 
|  | 126 | +| Public fields         |              2036 |               1602 | | 
|  | 127 | +| All-private structs   |      551 (52.23%) |       671 (63.60%) | | 
|  | 128 | +| All-public structs    |      468 (44.36%) |       352 (33.36%) | | 
|  | 129 | +| Mixed privacy structs |       36 ( 3.41%) |        32 ( 3.03%) | | 
|  | 130 | + | 
|  | 131 | +The numbers clearly show that the predominant pattern is to have all-private | 
|  | 132 | +structs, and that there are many public fields today which can be private (and | 
|  | 133 | +perhaps should!). Additionally, there is on the order of 1418 instances of the | 
|  | 134 | +word `priv` today, when in theory there should be around `1852`. With this RFC, | 
|  | 135 | +there would need to be `1602` instances of the word `pub`. A very large portion | 
|  | 136 | +of structs requiring `pub` fields are FFI structs defined in the `libc` | 
|  | 137 | +module. | 
|  | 138 | + | 
|  | 139 | +### Impact on enums | 
|  | 140 | + | 
|  | 141 | +This RFC does not impact enum variants in any way. All enum variants will | 
|  | 142 | +continue to inherit privacy from the outer enum type. This includes both the | 
|  | 143 | +fields of tuple variants as well as fields of struct variants in enums. | 
|  | 144 | + | 
|  | 145 | +# Alternatives | 
|  | 146 | + | 
|  | 147 | +The main alternative to this design is what is currently implemented today, | 
|  | 148 | +where fields inherit the privacy of the outer structure. The pros and cons of | 
|  | 149 | +this strategy are discussed above. | 
|  | 150 | + | 
|  | 151 | +# Unresolved questions | 
|  | 152 | + | 
|  | 153 | +As the above statistics show, almost all structures are either all public or all | 
|  | 154 | +private. This RFC provides an easy method to make struct fields all private, but | 
|  | 155 | +it explicitly does not provide a method to make struct fields all public. The | 
|  | 156 | +statistics show that `pub` will be written less often than `priv` is today, and | 
|  | 157 | +it's always possible to add a method to specify a struct as all-public in the | 
|  | 158 | +future in a backwards-compatible fashion. | 
|  | 159 | + | 
|  | 160 | +That being said, it's an open question whether syntax for an "all public struct" | 
|  | 161 | +is necessary at this time. | 
0 commit comments