@@ -4,7 +4,7 @@ Author: Bob Nystrom
4
4
5
5
Status: Accepted
6
6
7
- Version 2.24 (see [ CHANGELOG] ( #CHANGELOG ) at end)
7
+ Version 2.25 (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] [ ] .
@@ -1687,8 +1687,9 @@ To orchestrate this, type inference on patterns proceeds in three phases:
1687
1687
Using the pattern's type schema as a context type (if not in a matching
1688
1688
context), infer missing types on the value expression. This is the existing
1689
1689
type inference rules on expressions. It yields a complete static type for
1690
- the matched value. This process may also insert implicit coercions and casts
1691
- from ` dynamic ` in the matched value expression.
1690
+ the matched value. As usual, when a context type is applied to an
1691
+ expression, the process may also insert implicit coercions and casts from
1692
+ ` dynamic ` in the matched value expression.
1692
1693
1693
1694
* For example:*
1694
1695
@@ -1708,28 +1709,38 @@ To orchestrate this, type inference on patterns proceeds in three phases:
1708
1709
1709
1710
3. **Calculate the static type of the pattern.** Using that value type, recurse
1710
1711
through the pattern again downwards to the leaf subpatterns filling in any
1711
- missing types in the pattern. This process may also insert implicit
1712
- coercions and casts from `dynamic` when values flow into a pattern during
1713
- matching.
1712
+ missing types in the pattern. This process may also insert casts from
1713
+ `dynamic` when values flow into a pattern during matching.
1714
1714
1715
1715
*For example:*
1716
1716
1717
1717
```dart
1718
- T id<T>(T t) => t;
1719
- (T Function<T>(T), dynamic) record = (id, 'str');
1720
- var (int Function(int) f, String s) = record;
1718
+ (dynamic, dynamic) record = (123, 'str');
1719
+ var (int n, String s) = record;
1721
1720
```
1722
1721
1723
1722
*Since the right-hand is not a record literal, we can't use the pattern's
1724
1723
context type schema to insert coercions when the record is being created.
1725
- However, the matched value type `(T Function<T>(T), dynamic)` is allowed by
1726
- the record pattern's required type `(Object?, Object?)`, the field matched
1727
- value type `T Function<T>(T)` is allowed by the field required type `int
1728
- Function(int)`, and the field matched value type `dynamic` is allowed by the
1729
- field required type `String)`. So the declaration is valid. Coercions are
1730
- inserted after destructuring each record field before passing them to the
1731
- field subpatterns. At runtime, when the record is destructured during
1732
- matching, the coercions are applied. This is specified below.*
1724
+ However, the matched value type `(dynamic, dynamic)` is allowed by the
1725
+ record pattern's required type `(Object?, Object?)`, and the matched
1726
+ value type `dynamic` for each field is allowed by the required types
1727
+ of the fields, i.e., `int` and `String`, so the declaration is
1728
+ valid. Casts from dynamic are inserted after destructuring each record field
1729
+ before passing them to the field subpatterns.*
1730
+
1731
+ However, implicit call tear-off and implicit generic function instantiations
1732
+ are *not* inserted during destructuring. *Those implicit coercions are only
1733
+ inserted in _value expressions_ based on a pattern's context type schema,
1734
+ not during destructuring. For example:*
1735
+
1736
+ ```dart
1737
+ T id<T>(T t) => t;
1738
+ (T Function<T>(T),) record = (id,);
1739
+ var (int Function(int) f,) = record; // ERROR.
1740
+ ```
1741
+
1742
+ *This is a compile-time error since the record field type `T Function<T>(T)`
1743
+ is not allowed by the field subpattern required type `int Function(int)`.*
1733
1744
1734
1745
#### Pattern context type schema
1735
1746
@@ -2115,106 +2126,16 @@ To type check a pattern `p` being matched against a value of type `M`:
2115
2126
2116
2127
If `p` with required type `T` is in an irrefutable context:
2117
2128
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'.*
2124
-
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`.
2128
-
2129
- *Each pattern that requires a certain type can be thought of as an
2130
- "assignment point" where an implicit coercion may happen when a value flows
2131
- in during matching. Examples:*
2132
-
2133
- ```dart
2134
- var record = (x: 1 as dynamic);
2135
- var (x: String _) = record;
2136
- ```
2137
-
2138
- *Here no coercion is performed on the record pattern since `(x: dynamic)` is
2139
- a subtype of `(x: Object?)` (the record pattern's required type). But an
2140
- implicit cast from `dynamic` is inserted when the destructured `x` field
2141
- flows into the inner `String _` pattern, since `dynamic` is not a subtype of
2142
- `String`. In this example, the cast will fail and throw an exception.*
2129
+ * If `M` is `dynamic` and `T` is not `dynamic`, then an implicit cast from
2130
+ `dynamic` to `T` is made before the pattern binds the value, tests the
2131
+ value's type, destructures the value, or invokes a function with the value
2132
+ as a target or argument. *During destructuring, an implicit cast from
2133
+ `dynamic` is allowed, which may fail and throw an exception at runtime.*
2143
2134
2144
- ```dart
2145
- T id<T>(T t) => t;
2146
- var record = (x: id);
2147
- var (x: int Function(int) _) = record;
2148
- var list = [id];
2149
- var [int Function(int) idInt && String Function(String) idString] = list;
2150
- ```
2151
-
2152
- *Here, again no coercion is applied to the record flowing in to the record
2153
- pattern, but a generic instantiation is inserted when the destructured field
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.*
2158
-
2159
- *We only insert coercions in irrefutable contexts:*
2160
-
2161
- ```dart
2162
- dynamic d = 1;
2163
- if (d case String s) print('then') else print('else');
2164
- ```
2165
-
2166
- *This prints "else" instead of throwing an exception because we don't insert
2167
- a _cast_ from `dynamic` to `String` and instead let the `String s` pattern
2168
- _test_ the value's type, which then fails to match.*
2169
-
2170
- * Next, it is a compile-time error if `M` is not assignable to `T`.
2135
+ * Else, it is a compile-time error if `M` is not a subtype of `T`.
2171
2136
*Destructuring, variable, and identifier patterns can only be used in
2172
2137
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.*
2138
+ destructuring and variable binding won't fail to match.*
2218
2139
2219
2140
### Pattern uses (static semantics)
2220
2141
@@ -3608,6 +3529,11 @@ Here is one way it could be broken down into separate pieces:
3608
3529
3609
3530
## Changelog
3610
3531
3532
+ ### 2.25
3533
+
3534
+ - Call tear-off and generic function instantiations are not inserted during
3535
+ destructuring.
3536
+
3611
3537
### 2.24
3612
3538
3613
3539
- Specify the required type of patterns in cases where this was left implicit.
0 commit comments