@@ -4,7 +4,7 @@ Author: Bob Nystrom
4
4
5
5
Status: Accepted
6
6
7
- Version 2.23 (see [ CHANGELOG] ( #CHANGELOG ) at end)
7
+ Version 2.24 (see [ CHANGELOG] ( #CHANGELOG ) at end)
8
8
9
9
Note: This proposal is broken into a couple of separate documents. See also
10
10
[ records] [ ] and [ exhaustiveness] [ ] .
@@ -630,7 +630,7 @@ It is a compile-time error if:
630
630
element) will ever match. Duplicate keys are most likely a typo in the
631
631
code.*
632
632
633
- * Any two record keys which both have primitive ` == ` are equal. * Since
633
+ * Any two record keys which both have primitive equality are equal. * Since
634
634
records don't have defined identity, we can't use the previous rule to
635
635
detect identical records. But records do support an equality test known at
636
636
compile time if all of their fields do, so we use that.*
@@ -639,7 +639,7 @@ It is a compile-time error if:
639
639
640
640
* The ` ... ` element is not the last element in the map pattern.
641
641
642
- * Note that we don't require map keys to have primitive ` == ` methods to enable
642
+ * Note that we don't require map keys to have primitive equality, to enable
643
643
more flexibility in key types. If the keys have user-defined ` == ` methods, then
644
644
it's possible to have keys that are equal according to those ` == ` methods, but
645
645
the compiler won't detect it.*
@@ -687,8 +687,8 @@ Field subpatterns can be in one of three forms:
687
687
variable with the same name.
688
688
689
689
As a convenience, the identifier can be omitted and inferred from ` pattern ` .
690
- In this case the subpattern must be a variable pattern which may be wrapped
691
- in a unary pattern. The field name is then inferred from the name in the
690
+ In this case the subpattern must be a variable pattern which may be wrapped
691
+ in a unary pattern. The field name is then inferred from the name in the
692
692
variable pattern. These pairs of patterns are each equivalent:
693
693
694
694
``` dart
@@ -1869,7 +1869,7 @@ contexts, and the pattern type schema is only used in irrefutable contexts.
1869
1869
1870
1870
Once the value a pattern is matched against has a static type (which means
1871
1871
downwards inference on it using the pattern's context type schema is complete),
1872
- we can type check the pattern.
1872
+ we can type check the pattern and fill in missing parts (e.g., type arguments) .
1873
1873
1874
1874
Also variable, list, map, record, and object patterns only match a value of a
1875
1875
certain *required type*. These patterns are prohibited in an irrefutable context
@@ -1884,27 +1884,56 @@ var [int a, b] = <num>[1, 2]; // List<num>.
1884
1884
1885
1885
To type check a pattern ` p ` being matched against a value of type ` M ` :
1886
1886
1887
- * ** Logical-or** and ** logical-and** : Type check each branch using ` M ` as the
1888
- matched value type.
1887
+ * ** Logical-or** : Type check the first subpattern using ` M ` as the
1888
+ matched value type; type check the second subpattern using the matched value
1889
+ which is obtained from the assumption that the first operand failed to
1890
+ match * (this may cause promotion, e.g., when the left pattern is `==
1891
+ null` )*. The required type of the pattern is ` Object?`.
1892
+ * The context types will be used to perform checks on each operand, whose
1893
+ required types may be more strict.*
1894
+
1895
+ * ** Logical-and** : Type check the first operand using ` M ` as the matched
1896
+ value type, and type check the second operand using the (possibly promoted)
1897
+ matched value type obtained from the match-succeeded continuation of the
1898
+ first operand. The required type of the pattern is ` Object? ` .
1899
+ * The chosen matched value type will be used to perform checks on each
1900
+ operand, whose required types may be more strict.*
1901
+
1902
+ * ** Relational** : Consider the relational pattern ` op c ` where ` op ` is one
1903
+ of the following operators: ` == ` , ` != ` , ` < ` , ` <= ` , ` >= ` , ` > ` , and ` c ` is an
1904
+ expression.
1889
1905
1890
- * ** Relational** :
1906
+ A compile-time error occurs if ` M ` is ` void ` .
1907
+
1908
+ If ` M ` is ` dynamic ` or ` Never ` : Type check ` c ` in context ` _ ` ; an error
1909
+ occurs if ` c ` is not a constant expression; no further checks are
1910
+ performed. Otherwise * (when ` M ` is not ` dynamic ` or ` Never ` )* :
1911
+
1912
+ 1 . A compile-time error occurs if ` M ` does not have an operator ` op ` ,
1913
+ and there is no available and applicable extension operator ` op ` .
1914
+ Let ` A ` be the type of the formal parameter of the given operator
1915
+ declaration, and let ` R ` be the return type.
1916
+
1917
+ 2 . A compile-time error occurs if ` R ` is not assignable to ` bool ` .
1891
1918
1892
- 1 . Let ` C ` be the static type of the right operand constant expression.
1919
+ 3 . Type check ` c ` with context type ` A? ` when ` op ` is ` == ` or ` != ` , and
1920
+ with context type ` A ` otherwise. A compile-time error occurs if
1921
+ ` c ` is not a constant expression. Let ` C ` be the static type of ` c ` .
1893
1922
1894
- 2 . If the operator is a comparison (` < ` , ` <= ` , ` > ` , or ` >= ` ), then it is a
1895
- compile-time error if:
1923
+ 4 . If ` op ` is ` == ` or ` != ` then a compile-time error occurs if ` C ` is not
1924
+ assignable to ` A? ` . Otherwise ` op ` is ` < ` , ` <= ` , ` >= ` , or ` > ` , and a
1925
+ compile-time error occurs if ` C ` is not assignable to ` A ` .
1896
1926
1897
- * ` M ` does not define that operator,
1898
- * ` C ` is not assignable to the operator's parameter type,
1899
- * or if the operator's return type is not assignable to ` bool ` .
1927
+ * The language screens out ` null ` before calling the underlying ` == `
1928
+ method, which is why ` A? ` is the allowed type for equality checks. Since
1929
+ ` Object ` declares ` == ` to accept ` Object ` on the right, this compile-time
1930
+ error can only happen if a user-defined class has an override of ` == ` with a
1931
+ ` covariant ` parameter.*
1900
1932
1901
- 3 . Else the operator is ` == ` or ` != ` . It is a compile-time error if ` C ` is
1902
- not assignable to ` T? ` where ` T ` is ` M ` 's ` == ` method parameter type.
1903
- * The language screens out ` null ` before calling the underlying ` == `
1904
- method, which is why ` T? ` is the allowed type. Since Object declares
1905
- ` == ` to accept ` Object ` on the right, this compile-time error can only
1906
- happen if a user-defined class has an override of ` == ` with a
1907
- ` covariant ` parameter.*
1933
+ The required type of ` p ` is ` Object? ` . * The static checks mentioned above
1934
+ may give rise to compile-time errors, but there is no static type which
1935
+ would give rise to exactly those checks, so we cannot specify the desired
1936
+ checks simply by using any particular required type.*
1908
1937
1909
1938
* ** Cast** :
1910
1939
@@ -1913,6 +1942,8 @@ To type check a pattern `p` being matched against a value of type `M`:
1913
1942
1914
1943
2 . Type-check the subpattern using ` X ` as the matched value type.
1915
1944
1945
+ The required type of ` p ` is ` Object? ` .
1946
+
1916
1947
* ** Null-check** or ** null-assert** :
1917
1948
1918
1949
1 . Let ` N ` be [ ** NonNull** ] [ nonnull ] (` M ` ).
@@ -1926,8 +1957,8 @@ To type check a pattern `p` being matched against a value of type `M`:
1926
1957
int-to-double, and implicit generic function instantiation.*
1927
1958
1928
1959
* Note that the pattern's value must be a constant, but there is no longer a
1929
- restriction that it must have a primitive operator ` == ` . Unlike switch cases
1930
- in current Dart, you can have a constant with a user-defined operator ` == `
1960
+ restriction that it must have primitive equality . Unlike switch cases in
1961
+ current Dart, you can have a constant with a user-defined operator ` == `
1931
1962
method. This lets you use constant patterns for user-defined types with
1932
1963
custom value semantics.*
1933
1964
@@ -1979,7 +2010,7 @@ To type check a pattern `p` being matched against a value of type `M`:
1979
2010
static type of the variable introduced by `p`.
1980
2011
1981
2012
* **Parenthesized**: Type-check the inner subpattern using `M` as the matched
1982
- value type.
2013
+ value type. The required type of `p` is the required type of the subpattern.
1983
2014
1984
2015
* **List**:
1985
2016
@@ -2063,8 +2094,8 @@ To type check a pattern `p` being matched against a value of type `M`:
2063
2094
* **Object**:
2064
2095
2065
2096
1. Resolve the object name to a type `X`. It is a compile-time error if the
2066
- name does not refer to a type. Apply downwards inference from `M` to
2067
- infer type arguments for `X` if needed.
2097
+ name does not refer to a type. Apply downwards inference with context
2098
+ type `M` to infer type arguments for `X`, if needed.
2068
2099
2069
2100
2. For each field subpattern of `p`, with name `n` and subpattern `f`:
2070
2101
@@ -2084,16 +2115,16 @@ To type check a pattern `p` being matched against a value of type `M`:
2084
2115
2085
2116
If `p` with required type `T` is in an irrefutable context:
2086
2117
2087
- * It is a compile-time error if `M` is not assignable to `T`. *Destructuring,
2088
- variable, and identifier patterns can only be used in declarations and
2089
- assignments if we can statically tell that the destructuring and variable
2090
- binding won't fail to match (though it may still throw at runtime if the
2091
- matched value type is `dynamic`).*
2118
+ * If `M` is not a subtype of `T` and `M` is not `dynamic` then an attempt to
2119
+ insert an implicit coercion is made before the pattern binds the value,
2120
+ tests the value's type, destructures the value, or invokes a function with
2121
+ the value as a target or argument.
2122
+
2123
+ *Coercions are described in a separate section below, named 'Coercions'.*
2092
2124
2093
- * Else if `M` is not a subtype of `T` then an implicit coercion or cast is
2094
- inserted before the pattern binds the value, tests the value's type,
2095
- destructures the value, or invokes a function with the value as a target or
2096
- argument.
2125
+ If a coercion is inserted, this yields a new matched value type which is
2126
+ the value of `M` used in the next step. If no coercion is inserted, the
2127
+ next step proceeds with the already given `M`.
2097
2128
2098
2129
*Each pattern that requires a certain type can be thought of as an
2099
2130
"assignment point" where an implicit coercion may happen when a value flows
@@ -2107,18 +2138,23 @@ If `p` with required type `T` is in an irrefutable context:
2107
2138
*Here no coercion is performed on the record pattern since `(x: dynamic)` is
2108
2139
a subtype of `(x: Object?)` (the record pattern's required type). But an
2109
2140
implicit cast from `dynamic` is inserted when the destructured `x` field
2110
- flows into the inner `String _` pattern since `dynamic` is not a subtype of
2141
+ flows into the inner `String _` pattern, since `dynamic` is not a subtype of
2111
2142
`String`. In this example, the cast will fail and throw an exception.*
2112
2143
2113
2144
```dart
2114
2145
T id<T>(T t) => t;
2115
2146
var record = (x: id);
2116
2147
var (x: int Function(int) _) = record;
2148
+ var list = [id];
2149
+ var [int Function(int) idInt && String Function(String) idString] = list;
2117
2150
```
2118
2151
2119
2152
*Here, again no coercion is applied to the record flowing in to the record
2120
2153
pattern, but a generic instantiation is inserted when the destructured field
2121
- `x` field flows into the inner `int Function(int) _` pattern.*
2154
+ `x` flows into the inner `int Function(int) _` pattern. Similarly, no
2155
+ coercion is applied to the list, but generic function instantiations are
2156
+ applied when the list element flows into each of the operands of the
2157
+ logical-and pattern.*
2122
2158
2123
2159
*We only insert coercions in irrefutable contexts:*
2124
2160
@@ -2131,6 +2167,55 @@ If `p` with required type `T` is in an irrefutable context:
2131
2167
a _cast_ from `dynamic` to `String` and instead let the `String s` pattern
2132
2168
_test_ the value's type, which then fails to match.*
2133
2169
2170
+ * Next, it is a compile-time error if `M` is not assignable to `T`.
2171
+ *Destructuring, variable, and identifier patterns can only be used in
2172
+ declarations and assignments if we can statically tell that the
2173
+ destructuring and variable binding won't fail to match (though it may still
2174
+ throw at runtime if the matched value type is `dynamic`).*
2175
+
2176
+ ### Coercions
2177
+
2178
+ The language specification documents do not yet define a unified concept of
2179
+ _coercions_, and they do not define what it means to _attempt to insert a
2180
+ coercion_. However, the following is intended to establish these concepts
2181
+ in a sufficiently precise manner to enable the implementation of patterns:
2182
+
2183
+ The language supports the following mechanisms, which are the currently
2184
+ existing _coercions_:
2185
+
2186
+ - Implicit generic function instantiation.
2187
+ - Implicit tear-off of a `.call` method.
2188
+ - Implicit tear-off of a `.call` method, which is then generically instantiated.
2189
+
2190
+ These mechanisms are applied at specific locations *(known as assignment
2191
+ points)*, and they are enabled by specific pairs of context types and
2192
+ expression types.
2193
+
2194
+ *For example, implicit generic function instantiation is applied to an
2195
+ expression `e` whose type is a generic function type `G` in the case where
2196
+ the context type is a non-generic function type `F`, and `e` occurs at an
2197
+ assignment point. A list of actual type arguments are selected by type
2198
+ inference, yielding the expression `e<T1, .. Tk>`, such that the resulting
2199
+ expression has a type which is a subtype of `F`. If the type inference
2200
+ fails, or the resulting type is not a subtype of `F` then a compile-time
2201
+ error occurs. The implicit tear-off proceeds in a similar manner; it
2202
+ transforms `e` to `e.call` when the static type of `e` is an interface type
2203
+ that has a method named `call`, and the context type is a function type or
2204
+ `Function`.*
2205
+
2206
+ An _attempt to insert a coercion_ is the procedure which is described above. It
2207
+ may end in an application of the mechanism, or it may end in a compile-time
2208
+ error.
2209
+
2210
+ *In the context of pattern type checking, the compile-time error will
2211
+ generally report a lack of assignability, not, e.g., a failed type
2212
+ inference.*
2213
+
2214
+ *Note that the ability for an integer literal to have the type `double` is not a
2215
+ coercion *(for example `double d = 1;` makes `1` an integer literal with type
2216
+ `double`)*. Similarly, an implicit downcast from `dynamic` is not considered a
2217
+ coercion.*
2218
+
2134
2219
### Pattern uses (static semantics)
2135
2220
2136
2221
It is a compile-time error if the type of an expression in a guard clause is not
@@ -3523,6 +3608,11 @@ Here is one way it could be broken down into separate pieces:
3523
3608
3524
3609
## Changelog
3525
3610
3611
+ ### 2.24
3612
+
3613
+ - Specify the required type of patterns in cases where this was left implicit.
3614
+ - Specify the handling of coercions during irrefutable pattern matching.
3615
+
3526
3616
### 2.23
3527
3617
3528
3618
- Suggest warnings that implementations may want to report.
0 commit comments