Skip to content

Commit 5c6b6d3

Browse files
authored
Merge pull request #82 from dart-lang/const-spread
Support spread elements in const collections.
2 parents 19daba5 + a508fd9 commit 5c6b6d3

File tree

1 file changed

+40
-3
lines changed

1 file changed

+40
-3
lines changed

working/spread-collections/feature-specification.md

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,9 @@ become strict subtype checks instead.
281281

282282
### Const spreads
283283

284-
Spread elements are not allowed in const lists or maps. Because the spread must
285-
be imperatively unpacked, this could require arbitrary code to be executed at
286-
compile time:
284+
We must be careful with spread elements in const collections. Because the spread
285+
is imperatively unpacked, even a "const" object could cause arbitrary
286+
computation at compile time:
287287

288288
```dart
289289
class InfiniteSequence implements Iterable<int> {
@@ -300,6 +300,43 @@ class InfiniteSequence implements Iterable<int> {
300300
const forever = [...InfiniteSequence()];
301301
```
302302

303+
However, if the spread expression is a valid const expression and the resulting
304+
value is exactly the built-in List or Map classes, then it's safe because we
305+
know exactly how constants of those classes behave. Thus, we state:
306+
307+
* In a constant list, a spread element expands at compile time to the series
308+
of elements contained in the spread object list.
309+
310+
* In a constant map, a spread element expands to the series of entries
311+
contained in the spread object map.
312+
313+
* It is a compile-time error to use a spread element in a constant list unless
314+
the spread object was created by a constant list literal expression.
315+
316+
* It is a compile-time error to use a spread element in a constant map unless
317+
the spread object was created by from a constant map literal expression.
318+
319+
This enables in-place literals (which aren't very useful):
320+
321+
```dart
322+
const list = [...["why"]];
323+
```
324+
325+
It also enables const expressions that refer to constant lists and maps defined
326+
elsewhere, which is useful:
327+
328+
```dart
329+
const list = [2, 3];
330+
const another = [1, ...list, 4]; // [1, 2, 3, 4].
331+
```
332+
333+
The existing rules against self-reference prohibit a list or map from spreading
334+
into itself:
335+
336+
```dart
337+
const list = [...list]; // Error.
338+
```
339+
303340
### Type inference
304341

305342
Inference propagates upwards and downwards like you would expect:

0 commit comments

Comments
 (0)