Skip to content

Commit 8bcb3a4

Browse files
committed
[records] Allow private named fields.
Also loosen the naming restriction on positional fields in record types since those names are only used for documentation anyway. Fix #2387.
1 parent 1a70551 commit 8bcb3a4

File tree

1 file changed

+25
-13
lines changed

1 file changed

+25
-13
lines changed

accepted/future-releases/records/records-feature-specification.md

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,6 @@ not captured by the grammar. It is a compile-time error if a record has any of:
124124

125125
* A field named `hashCode`, `runtimeType`, `noSuchMethod`, or `toString`.
126126

127-
* A field name that starts with an underscore. *If we allow a record to have
128-
private field names, then those fields would not be visible outside of the
129-
library where the record was declared. That would lead to a record that has
130-
hidden state. Two such records might unexpectedly compare unequal even
131-
though all of the fields the user can see are equal.*
132-
133127
* A field name that collides with the synthesized getter name of a positional
134128
field. *For example: `('pos', $0: 'named')` since the named field '$0'
135129
collides with the getter for the first positional field.*
@@ -216,9 +210,8 @@ It is a compile-time error if a record type has any of:
216210
this is symmetric with record expressions and leaves the potential for
217211
later support for parentheses for grouping in type expressions.*
218212

219-
* A field named `hashCode`, `runtimeType`, `noSuchMethod`, or `toString`.
220-
221-
* A field name that starts with an underscore.
213+
* A positional field named `hashCode`, `runtimeType`, `noSuchMethod`, or
214+
`toString`.
222215

223216
* A field name that collides with the synthesized getter name of a positional
224217
field. *For example: `(int, $0: int)` since the named field '$0' collides
@@ -258,6 +251,11 @@ ambiguity, we disambiguate by treating `on` as a clause for `try` and not a
258251
local function. This is technically a breaking change, but is unlikely to affect
259252
any code in the wild.
260253

254+
**TODO: This section should be removed if we change the record type syntax to
255+
avoid this ambiguity ([#2469][]).**
256+
257+
[#2469]: https://github.com/dart-lang/language/issues/2469
258+
261259
## Static semantics
262260

263261
We define **shape** to mean the number of positional fields (the record's
@@ -266,8 +264,15 @@ structural, not nominal. Records produced in unrelated libraries have the exact
266264
same static type if they have the same shape and their corresponding fields have
267265
the same types.
268266

269-
The order of named fields is not significant. The record types `{int a, int b}`
270-
and `{int b, int a}` are identical to the type system and the runtime. (Tools
267+
If a field name starts with an underscore, it is private and is only accessible
268+
in the library where it appears. The records `(_foo: 1)` and `(_foo: 1)`
269+
appearing in different libraries do *not* have the same shape because each
270+
`_foo` is considered a distinct name. Likewise, the record types `({int _foo})`
271+
and `({int _foo})` are not the same type if those annotations appear in
272+
different libraries.
273+
274+
The order of named fields is not significant. The record types `({int a, int b})`
275+
and `({int b, int a})` are identical to the type system and the runtime. (Tools
271276
may or may not display them to users in a canonical form similar to how they
272277
handle function typedefs.)
273278

@@ -322,8 +327,8 @@ Likewise, the greatest lower bound of two record types with the same shape is
322327
the greatest lower bound of their component fields:
323328

324329
```dart
325-
a((num, String)) {}
326-
b((int, Object)) {}
330+
a((num, String) record) {}
331+
b((int, Object) record) {}
327332
var c = cond ? a : b; // c has type `Function((int, String))`.
328333
```
329334

@@ -577,6 +582,13 @@ covariant in their field types.
577582

578583
## CHANGELOG
579584

585+
### 1.10
586+
587+
- Allow private named fields in records (#2387).
588+
589+
- Allow positional fields in record types named `hashCode`, `runtimeType`,
590+
`noSuchMethod`, or `toString`.
591+
580592
### 1.9
581593

582594
- Specify that a record has a primitive `==` when its fields all do.

0 commit comments

Comments
 (0)