@@ -4,7 +4,7 @@ Author: Bob Nystrom
44
55Status: Accepted
66
7- Version 2.24 (see [ CHANGELOG] ( #CHANGELOG ) at end)
7+ Version 2.25 (see [ CHANGELOG] ( #CHANGELOG ) at end)
88
99Note: This proposal is broken into a couple of separate documents. See also
1010[ records] [ ] and [ exhaustiveness] [ ] .
@@ -1687,8 +1687,9 @@ To orchestrate this, type inference on patterns proceeds in three phases:
16871687 Using the pattern's type schema as a context type (if not in a matching
16881688 context), infer missing types on the value expression. This is the existing
16891689 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.
16921693
16931694 * For example:*
16941695
@@ -1708,28 +1709,38 @@ To orchestrate this, type inference on patterns proceeds in three phases:
17081709
170917103. **Calculate the static type of the pattern.** Using that value type, recurse
17101711 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.
17141714
17151715 *For example:*
17161716
17171717 ```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;
17211720 ```
17221721
17231722 *Since the right-hand is not a record literal, we can't use the pattern's
17241723 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)`.*
17331744
17341745#### Pattern context type schema
17351746
@@ -2115,106 +2126,16 @@ To type check a pattern `p` being matched against a value of type `M`:
21152126
21162127If `p` with required type `T` is in an irrefutable context:
21172128
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.*
21432134
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`.
21712136 *Destructuring, variable, and identifier patterns can only be used in
21722137 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.*
22182139
22192140### Pattern uses (static semantics)
22202141
@@ -3608,6 +3529,11 @@ Here is one way it could be broken down into separate pieces:
36083529
36093530## Changelog
36103531
3532+ ### 2.25
3533+
3534+ - Call tear-off and generic function instantiations are not inserted during
3535+ destructuring.
3536+
36113537### 2.24
36123538
36133539- Specify the required type of patterns in cases where this was left implicit.
0 commit comments