@@ -4,7 +4,7 @@ Author: Bob Nystrom
44
55Status: Accepted
66
7- Version 2.18 (see [ CHANGELOG] ( #CHANGELOG ) at end)
7+ Version 2.19 (see [ CHANGELOG] ( #CHANGELOG ) at end)
88
99Note: This proposal is broken into a couple of separate documents. See also
1010[ records] [ ] and [ exhaustiveness] [ ] .
@@ -595,6 +595,15 @@ It is a compile-time error if:
595595
596596* Any of the entry key expressions are not constant expressions.
597597
598+ * If any two keys in the map are identical. * Map patterns that don't have a
599+ rest element only match if the ` length ` of the map is equal to the number of
600+ map entries. If a map pattern has multiple identical key entries, they will
601+ increase the required length for the pattern to match but in all but the
602+ most perverse ` Map ` implementations will represent the same key. Thus, it's
603+ very unlikely that any map pattern containing identical keys (and no rest
604+ element) will ever match. Duplicate keys are most likely a typo in the
605+ code.*
606+
598607* If any two keys in the map both have primitive ` == ` methods, then it is a
599608 compile-time error if they are equal according to their ` == ` operator. * In
600609 cases where keys have types whose equality can be checked at compile time,
@@ -1231,6 +1240,67 @@ of an expression statement. This is similar to existing restrictions on map
12311240literals appearing in expression statements. In the rare case where a user
12321241really wants one there, they can parenthesize it.
12331242
1243+ #### Function expression in guard ambiguity
1244+
1245+ Function expressions also use ` => ` , which leads to a potential ambiguity:
1246+
1247+ ``` dart
1248+ var x = switch (obj) {
1249+ _ when a + (b) => (c) => body
1250+ };
1251+ ```
1252+
1253+ This could be interpreted as either:
1254+
1255+ ``` dart
1256+ var x = switch (obj) {
1257+ _ when (a + (b)) => ((c) => body)
1258+ // --------- -------------
1259+ };
1260+
1261+ var x = switch (obj) {
1262+ _ when (a + (b) => (c)) => (body)
1263+ // ---------------- ------
1264+ };
1265+ ```
1266+
1267+ A similar ambiguity exists with function expressions in initializer lists, if
1268+ the constructor happens to be a factory constructor with ` => ` for its body. We
1269+ resolve the ambiguity similarly here: When ` => ` is encountered after ` when ` in
1270+ a guard, if the code between forms a valid expression, then it is interpreted as
1271+ such and the ` => ` is treated as the separator between the guard and case body.
1272+ * In the above example, we take the first interpretation.*
1273+
1274+ This rules applies in all contexts where a guard can appear: switch statements,
1275+ switch elements, switch expressions, and if-case statements. * We could restrict
1276+ this rule to guards only in switch expressions where the ambiguity arises, but
1277+ that leads to a syntactic restriction that is context-sensitive and harder to
1278+ learn. Since the rule is unusual enough as it is, we apply it as consistently as
1279+ possible. Note that the related restriction on ` => ` in constructor initializers
1280+ applies even though generative constructors can't use ` => ` for their body.*
1281+
1282+ The rule is applied unconditionally even if the code after ` => ` is not a valid
1283+ body expression, as in:
1284+
1285+ ``` dart
1286+ var x = switch (obj) {
1287+ _ when (a) => b => c
1288+ };
1289+ ```
1290+
1291+ Here, we treat the guard expression as ` (a) ` , which leads the body to be `b =>
1292+ c` which isn't a valid expression and produces a compile-time error.
1293+
1294+ If you want a guard expression that ends in a function expression (which is
1295+ quite unlikely), you can avoid the ` => ` being captured as the case separator by
1296+ parenthesizing the function:
1297+
1298+ ``` dart
1299+ var x = switch (obj) {
1300+ _ when ((a) => b) => c
1301+ };
1302+ ```
1303+
12341304### If-case statement and element
12351305
12361306Often you want to conditionally match and destructure some data, but you only
@@ -2265,8 +2335,9 @@ All other types are not exhaustive. Then:
22652335 is to throw an error and most Dart users prefer to catch those kinds of
22662336 mistakes at compile time.*
22672337
2268- * It is a compile-time error if the cases in a switch statement are not
2269- exhaustive and the static type of the matched value is an exhaustive type.
2338+ * It is a compile-time error if the cases in a switch statement or switch
2339+ collection element are not exhaustive and the static type of the matched
2340+ value is an exhaustive type.
22702341
22712342[ exhaustiveness ] : https://github.com/dart-lang/language/blob/master/accepted/future-releases/0546-patterns/exhaustiveness.md
22722343
@@ -3122,6 +3193,14 @@ Here is one way it could be broken down into separate pieces:
31223193
31233194## Changelog
31243195
3196+ ### 2.19
3197+
3198+ - Specify exhaustiveness checking of switch elements.
3199+
3200+ - Resolve ambiguity with `=>` in switch expression guards (#2672).
3201+
3202+ - Compile error if map pattern has identical keys (#2657).
3203+
31253204### 2.18
31263205
31273206- Support negative number literals in patterns (#2663).
0 commit comments