@@ -35,8 +35,8 @@ also a restriction, as it requires you to have a wildcard arm in a `match` expre
35
35
are used on a daily basis by countless Rust programmers.
36
36
37
37
Restrictions are a powerful tool because the compiler stops you from doing something you are not
38
- allowed to do. If you violate a restriction by using trickery, such as transmuting a type, the
39
- resulting code is _ unsound_ .
38
+ allowed to do. If you violate a restriction by using unsafe trickery, such as transmuting a type,
39
+ the resulting code is _ unsound_ .
40
40
41
41
So why do we need restrictions? In fact, they are incredibly important. Those that have been around
42
42
a while will remember a time before ` #[non_exhaustive] ` . Standard practice at that point in time was
@@ -155,8 +155,8 @@ pub struct Time {
155
155
156
156
The author of ` time ` would love to have these fields public. However, they do not want users to be
157
157
able to change the values, as that would violate the invariants of the type. As a result they
158
- currently have to keep the fields private and write getters . What if, instead, they could add
159
- ` mut(crate) ` to a field, just like ` pub(crate) ` ? This would allow them to write:
158
+ currently have to keep the fields private and write "getter" methods . What if, instead, they could
159
+ add ` mut(crate) ` to a field, just like ` pub(crate) ` ? This would allow them to write:
160
160
161
161
``` rust
162
162
pub struct Time {
@@ -229,18 +229,19 @@ let x = Cell::new(5);
229
229
x . set (6 );
230
230
```
231
231
232
- Rust, as you may know, has [ interior mutability] . This is what we are using here. ` x ` is not
233
- declared mutable, and it does not need to be. This is the beauty of interior mutability. But it
234
- introduces a key question: where is the mutation? The answer is that it is ** not** a mutation for
235
- the purposes of this restriction. This is not because the value is not changed: it is. Rather, it is
236
- the logical result of the semantics of ` mut ` restrictions and where errors must occur (as described
237
- after the previous example). If errors are emitted at the point where the mutable reference is
238
- created, then there can be no such error here, as no mutable reference is ever created. ` Cell::set `
239
- is a method that takes ` &self ` , not ` &mut self ` . Surely we can make interior mutability a special
240
- case, right? No; the only way to work around this is to make any reference to a type with interior
241
- mutability considered a mutation. Consequently, you could never have a reference to a type
242
- containing a ` mut ` -restricted, interior-mutable field. This is unacceptable, so interior mutability
243
- cannot be considered a mutation for the purposes of this restriction.
232
+ Rust has [ interior mutability] , which is what we are using here. ` x ` is not declared mutable, and it
233
+ does not need to be. This is the purpose of interior mutability, by definition. But it introduces a
234
+ key question: where is the mutation? The answer is that it is ** not** a mutation for the purposes of
235
+ this restriction. This is not because the value is not changed: it is. Rather, it is the logical
236
+ result of the semantics of ` mut ` restrictions and where errors must occur (as described after the
237
+ previous example). If errors are emitted at the point where the mutable reference is created, then
238
+ there can be no such error here, as no mutable reference is ever created. ` Cell::set ` is a method
239
+ that takes ` &self ` , not ` &mut self ` . Interior mutability is not special-cased; the only way to work
240
+ around this would be to make even non-mutable reference to a type with interior mutability
241
+ considered a mutation. Consequently, you could never have a reference to a type containing a
242
+ ` mut ` -restricted, interior-mutable field. This is unacceptable, so interior mutability cannot be
243
+ considered a mutation for the purposes of this restriction. Interfaces that wish to restrict even
244
+ _ interior_ mutability of a field should avoid exposing it as a public field with private mutability.
244
245
245
246
[ interior mutability ] : https://doc.rust-lang.org/reference/interior-mutability.html
246
247
@@ -262,8 +263,8 @@ Time {
262
263
then the invariant would be violated, as there are only 24 hours in a day (numbered 0–23). Given
263
264
that the invariant is not enforced by the type system, it cannot be enforced at all in this case. As
264
265
a result, we have no choice but to disallow ` struct ` expressions for types with ` mut ` -restricted
265
- fields. This applies even when [ functional update syntax ] [ fru-syntax ] is used, as invariants can
266
- rely on the value of other fields.
266
+ fields, in scopes where any fields are ` mut ` -restricted. This applies even when
267
+ [ functional update syntax ] [ fru-syntax ] is used, as invariants can rely on the value of other fields.
267
268
268
269
[ fru-syntax ] : https://doc.rust-lang.org/stable/reference/expressions/struct-expr.html#functional-update-syntax
269
270
@@ -292,19 +293,18 @@ to the current crate. However, there are other ways to restrict visibility. You
292
293
` pub(super) ` to restrict visibility to the parent module, and ` pub(in path) ` to restrict visibility
293
294
to ` path ` , as long as that path is an ancestor of the location it is used. There is one additional
294
295
case you have likely never encountered: ` pub(self) ` . The reason you have likely never seen this
295
- before is that it is completely useless. Why? ` pub(self) ` is identical to private, which is the
296
- default visibility.
297
-
298
- While ` pub(self) ` should never be written in ordinary code, ` impl(self) ` and ` mut(self) ` are quite
299
- different. As the default restriction is unrestricted implementation and unrestricted mutation, it
300
- is more than likely that ` impl(self) ` and ` mut(self) ` will be quite common. During previous
301
- discussions about syntax, the unclear meaning of ` impl(self) ` and ` mut(self) ` was brought up. Syntax
302
- should have a clear meaning, and ` impl(self) ` and ` mut(self) ` are not clear. While they should be
303
- allowed for consistency with ` pub(self) ` , an alternative was needed with the same behavior.
304
- ` impl(mod) ` and ` mut(mod) ` should have a sufficiently clear meaning: implementing the trait and
305
- mutating the field are restricted to the current module. ` impl(in mod) ` and ` mut(in mod) ` are
306
- accepted as well. The behavior of ` impl(mod) ` is identical to ` impl(self) ` ; likewise for ` mut(mod) `
307
- and ` mut(self) ` .
296
+ before is that it is redundant: ` pub(self) ` is identical to private, which is the default
297
+ visibility.
298
+
299
+ While ` pub(self) ` should never be needed in most code, ` impl(self) ` and ` mut(self) ` are quite
300
+ different. As no restrictions apply by default (anything visible can be implemented/mutated), is
301
+ more than likely that ` impl(self) ` and ` mut(self) ` will be quite common. During previous discussions
302
+ about syntax, the unclear meaning of ` impl(self) ` and ` mut(self) ` was brought up. Syntax should have
303
+ a clear meaning, and ` impl(self) ` and ` mut(self) ` are not clear. While they should be allowed for
304
+ consistency with ` pub(self) ` , an alternative was needed with the same behavior. ` impl(mod) ` and
305
+ ` mut(mod) ` should have a sufficiently clear meaning: implementing the trait and mutating the field
306
+ are restricted to the current module. ` impl(in mod) ` and ` mut(in mod) ` are accepted as well. The
307
+ behavior of ` impl(mod) ` is identical to ` impl(self) ` ; likewise for ` mut(mod) ` and ` mut(self) ` .
308
308
309
309
For consistency with the new restriction syntax, ` pub(mod) ` and ` pub(in mod) ` are also allowed.
310
310
@@ -423,6 +423,7 @@ Trait aliases cannot be implemented. As such, there is no concern about compatib
423
423
# Alternatives
424
424
425
425
- ` impl ` and ` mut ` restrictions could be attributes, similar to ` #[non_exhaustive] ` .
426
+ - The proposed syntax could by syntactic sugar for these attributes.
426
427
427
428
# Prior art
428
429
@@ -436,6 +437,8 @@ Trait aliases cannot be implemented. As such, there is no concern about compatib
436
437
unhelpful to downstream users.
437
438
- Various other languages have read-only fields, including C++, C#, Java, TypeScript, Kotlin, and
438
439
Swift.
440
+ - Users of many languages, including Rust, regularly implement read-only fields by providing a
441
+ getter method without a setter method, demonstrating a need for this.
439
442
440
443
# Unresolved questions
441
444
@@ -456,11 +459,14 @@ Trait aliases cannot be implemented. As such, there is no concern about compatib
456
459
457
460
# Future possibilities
458
461
459
- - Sealed /exhaustive traits could happen in the future. This has the ability to impact coherence,
460
- such that other crates could rely on the fact that the list of implementations is exhaustive. As
461
- traits would default to unsealed, this does not have be decided now.
462
+ - Explicitly sealed /exhaustive traits could happen in the future. This has the ability to impact
463
+ coherence, such that other crates could rely on the fact that the list of implementations is
464
+ exhaustive. As traits would default to unsealed, this does not have be decided now.
462
465
- Trait items could gain proper visibility and/or restrictions of their own. This would allow
463
466
private and/or defaulted trait items that cannot be overridden.
464
467
- Set-once fields could potentially occur in the future. Functionally, this would be "true"
465
468
read-only fields, in that they can be constructed but never mutated. They are not included in this
466
469
proposal as the use case is nor clear, nor is there an immediately obvious syntax to support this.
470
+ - The default could be changed in a future edition, such as to make ` pub field: Type ` be only
471
+ mutable within the module rather than mutable everywhere. This seems unlikely, as it would be an
472
+ incredibly disruptive change, and the benefits would have to be significant.
0 commit comments