@@ -903,8 +903,8 @@ forLoopParts ::=
903
903
| metadata ( 'final' | 'var' ) outerPattern 'in' expression // New.
904
904
```
905
905
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 .
908
908
909
909
* We could potentially allow patterns in top-level variables and static fields
910
910
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:
1680
1680
object, and not necessarily to try to force a certain answer.*
1681
1681
1682
1682
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,
1685
1686
it's the value being matched.
1686
1687
1687
1688
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
2211
2212
set, defined above), are introduced into a scope based on where the pattern
2212
2213
appears:
2213
2214
2214
- * **Pattern variable declaration**: The scope enclosing the variable
2215
+ * **Pattern variable declaration statement **: The scope enclosing the variable
2215
2216
declaration statement. *This will be either a function body scope or a block
2216
2217
scope.*
2217
2218
2218
2219
The *initializing expression* for every variable in the pattern is the
2219
2220
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
2221
2222
block or function body, but it is a compile-time error to refer to them
2222
2223
until after the pattern variable declaration's initializer:*
2223
2224
@@ -2236,11 +2237,15 @@ appears:
2236
2237
}
2237
2238
```
2238
2239
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.
2244
2249
2245
2250
* **Pattern assignment**: An assignment only assigns to existing variables
2246
2251
and does not bind any new ones.
@@ -2611,11 +2616,11 @@ A statement of the form:
2611
2616
for (<patternVariableDeclaration>; <condition>; <increment>) <statement>
2612
2617
```
2613
2618
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.
2619
2624
2620
2625
The increment clause is evaluated in a scope where all variables declared in the
2621
2626
pattern are freshly bound to new variables holding the current iteration's
@@ -2638,6 +2643,22 @@ for (var fn in fns) {
2638
2643
2639
2644
This prints ` 0 ` , ` 1 ` , ` 1 ` , ` 2 ` , ` 3 ` , ` 5 ` , ` 8 ` , ` 13 ` .
2640
2645
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
+
2641
2662
#### Pattern-for-in statement
2642
2663
2643
2664
A statement of the form:
@@ -2648,7 +2669,8 @@ for (<keyword> <pattern> in <expression>) <statement>
2648
2669
2649
2670
Where ` <keyword> ` is ` var ` or ` final ` is treated like so:
2650
2671
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> ` .
2652
2674
2653
2675
2 . Calculate the element type of ` I ` :
2654
2676
@@ -2672,6 +2694,42 @@ Where `<keyword>` is `var` or `final` is treated like so:
2672
2694
}
2673
2695
```
2674
2696
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
+
2675
2733
#### If-case statement
2676
2734
2677
2735
1. Evaluate the `expression` producing `v`.
@@ -3493,6 +3551,11 @@ Here is one way it could be broken down into separate pieces:
3493
3551
- Clarify that map pattern keys and relational pattern right operands are not
3494
3552
const contexts (#2758).
3495
3553
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
+
3496
3559
[co19 #1686]: https://github.com/dart-lang/co19/issues/1686#issuecomment-1386192988
3497
3560
3498
3561
### 2.20
0 commit comments