Skip to content

Support spread elements in const collections. #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 8, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions working/spread-collections/feature-specification.md
Original file line number Diff line number Diff line change
@@ -247,9 +247,9 @@ become strict subtype checks instead.

### Const spreads

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

```dart
class InfiniteSequence implements Iterable<int> {
@@ -266,6 +266,43 @@ class InfiniteSequence implements Iterable<int> {
const forever = [...InfiniteSequence()];
```

However, if the spread expression is a valid const expression and the resulting
value is exactly the built-in List or Map classes, then it's safe because we
know exactly how constants of those classes behave. Thus, we state:

* In a constant list, a spread element expands at compile time to the series
of elements contained in the spread object list.

* In a constant map, a spread element expands to the series of entries
contained in the spread object map.

* It is a compile-time error to use a spread element in a constant list unless
the spread object was created by a constant list literal expression.

* It is a compile-time error to use a spread element in a constant map unless
the spread object was created by from a constant map literal expression.

This enables in-place literals (which aren't very useful):

```dart
const list = [...["why"]];
```

It also enables const expressions that refer to constant lists and maps defined
elsewhere, which is useful:

```dart
const list = [2, 3];
const another = [1, ...list, 4]; // [1, 2, 3, 4].
```

The existing rules against self-reference prohibit a list or map from spreading
into itself:

```dart
const list = [...list]; // Error.
```

### Type inference

Inference propagates upwards and downwards like you would expect: