Skip to content

Commit 6a13f89

Browse files
authored
[patterns] Specify the behavior of pattern-for collection elements. (#2777)
* [patterns] Specify the behavior of pattern-for collection elements. Fix #2769. * Add other small change to CHANGELOG. Fix #2775. * Revise.
1 parent c696942 commit 6a13f89

File tree

1 file changed

+80
-17
lines changed

1 file changed

+80
-17
lines changed

accepted/future-releases/0546-patterns/feature-specification.md

Lines changed: 80 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -903,8 +903,8 @@ forLoopParts ::=
903903
| metadata ( 'final' | 'var' ) outerPattern 'in' expression // New.
904904
```
905905

906-
As with regular for-in loops, it is a compile-time error if the type of
907-
`expression` in a pattern-for-in loop is not assignable to `Iterable<dynamic>`.
906+
This allows patterns inside local variable declarations, for statements, for-in
907+
statements, for collection elements, and for-in collection elements.
908908

909909
*We could potentially allow patterns in top-level variables and static fields
910910
but lazy initialization makes that more complex. We could support patterns in
@@ -1680,8 +1680,9 @@ To orchestrate this, type inference on patterns proceeds in three phases:
16801680
object, and not necessarily to try to force a certain answer.*
16811681

16821682
2. **Calculate the static type of the matched value.** A pattern always occurs
1683-
in the context of some matched value. For pattern variable declarations and
1684-
assignments, this is the initializer. For switches and if-case constructs,
1683+
in the context of some matched value. For pattern variable declarations
1684+
including inside for and for-in loops, this is the initializer. For pattern
1685+
assignments, it's the assigned value. For switches and if-case constructs,
16851686
it's the value being matched.
16861687

16871688
Using the pattern's type schema as a context type (if not in a matching
@@ -2211,13 +2212,13 @@ The variables defined by a pattern and its subpatterns (its pattern variable
22112212
set, defined above), are introduced into a scope based on where the pattern
22122213
appears:
22132214
2214-
* **Pattern variable declaration**: The scope enclosing the variable
2215+
* **Pattern variable declaration statement**: The scope enclosing the variable
22152216
declaration statement. *This will be either a function body scope or a block
22162217
scope.*
22172218
22182219
The *initializing expression* for every variable in the pattern is the
22192220
pattern variable declaration's initializer. *This means all variables
2220-
defined by a pattern are in scope beginning at the top of the surrounding
2221+
defined by the pattern are in scope beginning at the top of the surrounding
22212222
block or function body, but it is a compile-time error to refer to them
22222223
until after the pattern variable declaration's initializer:*
22232224
@@ -2236,11 +2237,15 @@ appears:
22362237
}
22372238
```
22382239
2239-
* **Pattern-for statement**: Scoping follows the normal for and for-in
2240-
statement scoping rules where the variable (now variables) are bound in a
2241-
new scope for each loop iteration. All pattern variables are in the same
2242-
scope. They are considered initialized after the for loop initializer
2243-
expression.
2240+
* **Pattern-for statement**, **pattern-for-in element**, **pattern-for
2241+
statement**, **pattern-for element**: Scoping follows the normal for and
2242+
for-in statement and elements scoping rules where the variable (now
2243+
variables) are bound in a new scope for each loop iteration. All pattern
2244+
variables are in the same scope. They are considered initialized after the
2245+
for loop initializer expression.
2246+
2247+
The body statement or element of a pattern-for is executed in a new scope
2248+
whose enclosing scope is the pattern variables' scope.
22442249
22452250
* **Pattern assignment**: An assignment only assigns to existing variables
22462251
and does not bind any new ones.
@@ -2611,11 +2616,11 @@ A statement of the form:
26112616
for (<patternVariableDeclaration>; <condition>; <increment>) <statement>
26122617
```
26132618

2614-
Is executed similar to a traditional for loop except that multiple variables may
2615-
be declared by the pattern instead of just one. As with a normal for loop, those
2616-
variables are freshly bound to new values at each iteration so that if a
2617-
function closes over a variable, it captures the value at the current iteration
2618-
and is not affected by later iteration.
2619+
Is executed like a traditional for loop though is more likely to declare
2620+
multiple variables. As with a normal for loop, those variables are freshly bound
2621+
to new values at each iteration so that if a function in the body closes over a
2622+
variable, it captures the value at the current iteration and is not affected by
2623+
later iteration.
26192624

26202625
The increment clause is evaluated in a scope where all variables declared in the
26212626
pattern are freshly bound to new variables holding the current iteration's
@@ -2638,6 +2643,22 @@ for (var fn in fns) {
26382643

26392644
This prints `0`, `1`, `1`, `2`, `3`, `5`, `8`, `13`.
26402645

2646+
#### Pattern-for element
2647+
2648+
Likewise, a collection element of the form:
2649+
2650+
```dart
2651+
for (<patternVariableDeclaration>; <condition>; <increment>) <element>
2652+
```
2653+
2654+
Is executed like a traditional for loop though is more likely to declare
2655+
multiple variables. As with pattern for statements, all of the variables are
2656+
declared fresh every iteration and updates to the variables in the increment
2657+
clause behave as other loops do.
2658+
2659+
The `<element>` is evaluated in a new scope whose enclosing scope is the scope
2660+
where the pattern's variables are bound.
2661+
26412662
#### Pattern-for-in statement
26422663

26432664
A statement of the form:
@@ -2648,7 +2669,8 @@ for (<keyword> <pattern> in <expression>) <statement>
26482669

26492670
Where `<keyword>` is `var` or `final` is treated like so:
26502671

2651-
1. Let `I` be the type of `<expression>`.
2672+
1. Let `I` be the static type of `<expression>`, inferred using the context
2673+
type schema of `<pattern>`.
26522674

26532675
2. Calculate the element type of `I`:
26542676

@@ -2672,6 +2694,42 @@ Where `<keyword>` is `var` or `final` is treated like so:
26722694
}
26732695
```
26742696
2697+
#### Pattern-for-in element
2698+
2699+
A collection element of the form:
2700+
2701+
```dart
2702+
for (<keyword> <pattern> in <expression>) <element>
2703+
```
2704+
2705+
Where `<keyword>` is `var` or `final` is treated like so:
2706+
2707+
1. Let `I` be the static type of `<expression>`, inferred using the context
2708+
type schema of `<pattern>`.
2709+
2710+
2. Calculate the element type of `I`:
2711+
2712+
1. If `I` implements `Iterable<T>` for some `T` then `E` is `T`.
2713+
2714+
2. Else if `I` is `dynamic` then `E` is `dynamic`.
2715+
2716+
3. Else it is a compile-time error.
2717+
2718+
3. Type check `<pattern>` with matched value type `E`.
2719+
2720+
4. If there are no compile-time errors, then execution proceeds as the
2721+
following code, where `id1` and `id2` are fresh identifiers and `append()`
2722+
is an operation to add an element to the surrounding collection being built:
2723+
2724+
```
2725+
I id1 = <expression>;
2726+
Iterator<E> id2 = id1.iterator;
2727+
while (id2.moveNext()) {
2728+
<keyword> <pattern> = id2.current;
2729+
append(<element>);
2730+
}
2731+
```
2732+
26752733
#### If-case statement
26762734
26772735
1. Evaluate the `expression` producing `v`.
@@ -3493,6 +3551,11 @@ Here is one way it could be broken down into separate pieces:
34933551
- Clarify that map pattern keys and relational pattern right operands are not
34943552
const contexts (#2758).
34953553
3554+
- Specify the runtime behavior of pattern-for collection elements (#2769).
3555+
3556+
- Clarify the inference context for the iterator expression in pattern for-in
3557+
statements (#2775).
3558+
34963559
[co19 #1686]: https://github.com/dart-lang/co19/issues/1686#issuecomment-1386192988
34973560
34983561
### 2.20

0 commit comments

Comments
 (0)