From 23460427c1cc262c5931f7f15f8c95ee126c40d6 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Thu, 30 Mar 2023 15:35:32 +0300 Subject: [PATCH 1/7] Fixes #1976. Update map pattern tests according to the new matching rules --- .../Patterns/invocation_keys_A08_t01.dart | 19 +- .../Patterns/invocation_keys_A08_t02.dart | 19 +- .../Patterns/invocation_keys_A08_t03.dart | 27 ++- .../Patterns/invocation_keys_A08_t04.dart | 9 +- LanguageFeatures/Patterns/map_A01_t01.dart | 27 +-- LanguageFeatures/Patterns/map_A01_t02.dart | 27 +-- LanguageFeatures/Patterns/map_A01_t03.dart | 27 +-- LanguageFeatures/Patterns/map_A01_t04.dart | 27 +-- LanguageFeatures/Patterns/map_A02_t01.dart | 27 +-- LanguageFeatures/Patterns/map_A02_t02.dart | 27 +-- LanguageFeatures/Patterns/map_A03_t01.dart | 27 +-- LanguageFeatures/Patterns/map_A04_t01.dart | 173 ++++++------------ LanguageFeatures/Patterns/map_A04_t02.dart | 27 +-- LanguageFeatures/Patterns/map_A05_t01.dart | 162 +++++++--------- LanguageFeatures/Patterns/map_A06_t01.dart | 51 ++---- LanguageFeatures/Patterns/map_A07_t01.dart | 116 +++++++----- LanguageFeatures/Patterns/map_A08_t01.dart | 111 +++++------ LanguageFeatures/Patterns/map_A08_t02.dart | 140 -------------- .../Patterns/matching_map_A01_t01.dart | 15 +- .../Patterns/matching_map_A02_t01.dart | 58 +++--- .../Patterns/matching_map_A02_t02.dart | 45 ++--- .../Patterns/matching_map_A02_t03.dart | 75 +++----- .../Patterns/matching_map_A02_t04.dart | 49 +++-- ...A03_t05.dart => matching_map_A02_t05.dart} | 27 +-- ...A03_t06.dart => matching_map_A02_t06.dart} | 27 +-- .../Patterns/matching_map_A03_t01.dart | 46 ++--- .../Patterns/matching_map_A03_t02.dart | 52 ++---- .../Patterns/matching_map_A03_t03.dart | 53 ++---- .../Patterns/matching_map_A03_t04.dart | 119 ------------ .../Patterns/matching_map_A04_t01.dart | 107 ----------- .../Patterns/matching_map_A04_t02.dart | 107 ----------- .../Patterns/matching_map_A04_t03.dart | 106 ----------- 32 files changed, 485 insertions(+), 1444 deletions(-) delete mode 100644 LanguageFeatures/Patterns/map_A08_t02.dart rename LanguageFeatures/Patterns/{matching_map_A03_t05.dart => matching_map_A02_t05.dart} (79%) rename LanguageFeatures/Patterns/{matching_map_A03_t06.dart => matching_map_A02_t06.dart} (79%) delete mode 100644 LanguageFeatures/Patterns/matching_map_A03_t04.dart delete mode 100644 LanguageFeatures/Patterns/matching_map_A04_t01.dart delete mode 100644 LanguageFeatures/Patterns/matching_map_A04_t02.dart delete mode 100644 LanguageFeatures/Patterns/matching_map_A04_t03.dart diff --git a/LanguageFeatures/Patterns/invocation_keys_A08_t01.dart b/LanguageFeatures/Patterns/invocation_keys_A08_t01.dart index a9c83e974c..b1833c7617 100644 --- a/LanguageFeatures/Patterns/invocation_keys_A08_t01.dart +++ b/LanguageFeatures/Patterns/invocation_keys_A08_t01.dart @@ -17,15 +17,14 @@ /// To bind invocation keys in a pattern p using parent invocation i: /// ... /// Map: -/// i. Bind i : ("length", []) to the length getter invocation. -/// ii. For each entry in p: +/// i. For each entry in p: /// a. Bind i : ("containsKey()", [key]) to the containsKey() invocation where /// key is entry's key constant value. /// b. Let e be i : ("[]", [key]) where key is entry's key constant value. /// c. Bind e to the [] invocation for this entry. /// d. Bind invocations in the entry value subpattern using parent e. /// -/// @description Checks that for a map pattern invocation keys `("length", [])`, +/// @description Checks that for a map pattern invocation keys /// `("containsKey()", [key])` and `("[]", [key])` are invoked only once. /// @author sgrekhov22@gmail.com @@ -37,9 +36,9 @@ import "patterns_collections_lib.dart"; String test1(Object o) { switch (o) { - case {"key1": 1}: // Expect call length + case {"key1": 2}: // Expect call [key1] return "match-1"; - case {"key1": 1, "key2": 3}: // Expect call [key1], [key2] + case {"key1": 1, "key2": 3}: // Expect call [key2] return "match-2"; case {"key1": 1, "key2": 2}: // Expect no additional calls return "match-3"; @@ -50,7 +49,7 @@ String test1(Object o) { String test2(Object o) => switch (o) { - {"key1": 1} => "match-1", + {"key1": 2} => "match-1", {"key1": 1, "key2": 3} => "match-2", {"key1": 1, "key2": 2} => "match-3", _ => "no match" @@ -59,17 +58,17 @@ String test2(Object o) => main() { final map = MyMap({"key1": 1, "key2": 2}); Expect.equals("match-3", test1(map)); - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); Expect.equals("match-3", test2(map)); - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); var {"key1": x1, "key2": x2} = map; - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); final {"key1": y1, "key2": y2} = map; - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("[key1];[key2];", map.log); } diff --git a/LanguageFeatures/Patterns/invocation_keys_A08_t02.dart b/LanguageFeatures/Patterns/invocation_keys_A08_t02.dart index d987d1a321..3b13584b5d 100644 --- a/LanguageFeatures/Patterns/invocation_keys_A08_t02.dart +++ b/LanguageFeatures/Patterns/invocation_keys_A08_t02.dart @@ -17,15 +17,14 @@ /// To bind invocation keys in a pattern p using parent invocation i: /// ... /// Map: -/// i. Bind i : ("length", []) to the length getter invocation. -/// ii. For each entry in p: +/// i. For each entry in p: /// a. Bind i : ("containsKey()", [key]) to the containsKey() invocation where /// key is entry's key constant value. /// b. Let e be i : ("[]", [key]) where key is entry's key constant value. /// c. Bind e to the [] invocation for this entry. /// d. Bind invocations in the entry value subpattern using parent e. /// -/// @description Checks that for a map pattern invocation keys `("length", [])`, +/// @description Checks that for a map pattern invocation keys /// `("containsKey()", [key])` and `("[]", [key])` are invoked only once. /// @author sgrekhov22@gmail.com @@ -37,9 +36,9 @@ import "patterns_collections_lib.dart"; String test1(Object o) { switch (o) { - case {"key1": 1}: // Expect call length + case {"key1": 2}: // Expect call [key1] return "match-1"; - case {"key1": 1, "key2": 3}: // Expect call [key1], [key2], containsKey(key2) + case {"key1": 1, "key2": 3}: // Expect call [key2], containsKey(key2) return "match-2"; case {"key1": 1, "key2": 2}: // Expect no additional calls return "match-3"; @@ -50,7 +49,7 @@ String test1(Object o) { String test2(Object o) => switch (o) { - {"key1": 1} => "match-1", + {"key1": 2} => "match-1", {"key1": 1, "key2": 3} => "match-2", {"key1": 1, "key2": 2} => "match-3", _ => "no match" @@ -59,17 +58,17 @@ String test2(Object o) => main() { final map = MyMap({"key1": 1, "key2": null}); Expect.equals("no match", test1(map)); - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); + Expect.equals("[key1];[key2];containsKey(key2);", map.log); map.clearLog(); Expect.equals("no match", test2(map)); - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); + Expect.equals("[key1];[key2];containsKey(key2);", map.log); map.clearLog(); var {"key1": x1, "key2": x2} = map; - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); + Expect.equals("[key1];[key2];containsKey(key2);", map.log); map.clearLog(); final {"key1": y1, "key2": y2} = map; - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); + Expect.equals("[key1];[key2];containsKey(key2);", map.log); } diff --git a/LanguageFeatures/Patterns/invocation_keys_A08_t03.dart b/LanguageFeatures/Patterns/invocation_keys_A08_t03.dart index 5ae5350242..bfec0c85ec 100644 --- a/LanguageFeatures/Patterns/invocation_keys_A08_t03.dart +++ b/LanguageFeatures/Patterns/invocation_keys_A08_t03.dart @@ -17,15 +17,14 @@ /// To bind invocation keys in a pattern p using parent invocation i: /// ... /// Map: -/// i. Bind i : ("length", []) to the length getter invocation. -/// ii. For each entry in p: +/// i. For each entry in p: /// a. Bind i : ("containsKey()", [key]) to the containsKey() invocation where /// key is entry's key constant value. /// b. Let e be i : ("[]", [key]) where key is entry's key constant value. /// c. Bind e to the [] invocation for this entry. /// d. Bind invocations in the entry value subpattern using parent e. /// -/// @description Checks that for a map pattern invocation keys `("length", [])`, +/// @description Checks that for a map pattern invocation keys /// `("containsKey()", [key])` and `("[]", [key])` are invoked only once. /// @author sgrekhov22@gmail.com @@ -37,11 +36,11 @@ import "patterns_collections_lib.dart"; String test1(Object o) { switch (o) { - case {"key1": 1}: // Expect call length + case {"key1": 2}: // Expect call [key1] return "match-1"; - case {"key1": _, "key2": 3}: // Expect call [key1], [key2] + case {"key1": _, "key2": 3}: // Expect call [key2] return "match-2"; - case {"key1": _, "key2": _, ...}: // Expect no additional calls + case {"key1": _, "key2": _}: // Expect no additional calls return "match-3"; default: return "no match"; @@ -50,26 +49,26 @@ String test1(Object o) { String test2(Object o) => switch (o) { - {"key1": 1} => "match-1", + {"key1": 2} => "match-1", {"key1": _, "key2": 3} => "match-2", - {"key1": _, "key2": _, ...} => "match-3", + {"key1": _, "key2": _} => "match-3", _ => "no match" }; main() { final map = MyMap({"key1": 1, "key2": 2}); Expect.equals("match-3", test1(map)); - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); Expect.equals("match-3", test2(map)); - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); - var {"key1": _, "key2": _, ...} = map; - Expect.equals("length;[key1];[key2];", map.log); + var {"key1": _, "key2": _} = map; + Expect.equals("[key1];[key2];", map.log); map.clearLog(); - final {"key1": _, "key2": _, ...} = map; - Expect.equals("length;[key1];[key2];", map.log); + final {"key1": _, "key2": _} = map; + Expect.equals("[key1];[key2];", map.log); } diff --git a/LanguageFeatures/Patterns/invocation_keys_A08_t04.dart b/LanguageFeatures/Patterns/invocation_keys_A08_t04.dart index fb7f09da59..4576cc948c 100644 --- a/LanguageFeatures/Patterns/invocation_keys_A08_t04.dart +++ b/LanguageFeatures/Patterns/invocation_keys_A08_t04.dart @@ -17,8 +17,7 @@ /// To bind invocation keys in a pattern p using parent invocation i: /// ... /// Map: -/// i. Bind i : ("length", []) to the length getter invocation. -/// ii. For each entry in p: +/// i. For each entry in p: /// a. Bind i : ("containsKey()", [key]) to the containsKey() invocation where /// key is entry's key constant value. /// b. Let e be i : ("[]", [key]) where key is entry's key constant value. @@ -37,7 +36,7 @@ import "patterns_collections_lib.dart"; String test1(Object o) { switch (o) { - case >[{"key1": 1}, {"key1": 2}]: // Expect call length, ["key1"], length, ["key1] + case >[{"key1": 1}, {"key1": 2}]: // Expect call ["key1"], ["key1] return "match-1"; case >[{"key1": 1}, {"key1": _}]: // Expect no new calls return "match-2"; @@ -56,9 +55,9 @@ String test2(Object o) => main() { final map = MyMap({"key1": 1}); Expect.equals("match-2", test1([map, map])); - Expect.equals("length;[key1];length;[key1];", map.log); + Expect.equals("[key1];[key1];", map.log); map.clearLog(); Expect.equals("match-2", test2([map, map])); - Expect.equals("length;[key1];length;[key1];", map.log); + Expect.equals("[key1];[key1];", map.log); } diff --git a/LanguageFeatures/Patterns/map_A01_t01.dart b/LanguageFeatures/Patterns/map_A01_t01.dart index 220d60bbd9..150b5ab060 100644 --- a/LanguageFeatures/Patterns/map_A01_t01.dart +++ b/LanguageFeatures/Patterns/map_A01_t01.dart @@ -5,33 +5,14 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: -/// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// /// @description Checks a map pattern with different subpatterns in a switch /// expression diff --git a/LanguageFeatures/Patterns/map_A01_t02.dart b/LanguageFeatures/Patterns/map_A01_t02.dart index 0ecc7d8bec..071e2927b6 100644 --- a/LanguageFeatures/Patterns/map_A01_t02.dart +++ b/LanguageFeatures/Patterns/map_A01_t02.dart @@ -5,33 +5,14 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: -/// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// /// @description Checks a map pattern with different subpatterns in a switch /// statement diff --git a/LanguageFeatures/Patterns/map_A01_t03.dart b/LanguageFeatures/Patterns/map_A01_t03.dart index 1f0fbd1241..3ac12121b7 100644 --- a/LanguageFeatures/Patterns/map_A01_t03.dart +++ b/LanguageFeatures/Patterns/map_A01_t03.dart @@ -5,33 +5,14 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: -/// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// /// @description Checks a map pattern with different subpatterns in an if-case /// statement diff --git a/LanguageFeatures/Patterns/map_A01_t04.dart b/LanguageFeatures/Patterns/map_A01_t04.dart index 99c292f337..9c71c7f454 100644 --- a/LanguageFeatures/Patterns/map_A01_t04.dart +++ b/LanguageFeatures/Patterns/map_A01_t04.dart @@ -5,33 +5,14 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: -/// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// /// @description Checks a map pattern in a declaration context /// @author sgrekhov22@gmail.com diff --git a/LanguageFeatures/Patterns/map_A02_t01.dart b/LanguageFeatures/Patterns/map_A02_t01.dart index 8efd1ca353..66f8ff513e 100644 --- a/LanguageFeatures/Patterns/map_A02_t01.dart +++ b/LanguageFeatures/Patterns/map_A02_t01.dart @@ -5,33 +5,14 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: -/// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// /// @description Check that it is a compile-time error if typeArguments is /// present and there are more or fewer than two type arguments diff --git a/LanguageFeatures/Patterns/map_A02_t02.dart b/LanguageFeatures/Patterns/map_A02_t02.dart index 96b201aad9..c19d862c20 100644 --- a/LanguageFeatures/Patterns/map_A02_t02.dart +++ b/LanguageFeatures/Patterns/map_A02_t02.dart @@ -5,33 +5,14 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: -/// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// /// @description Check that it is a compile-time error if one typeArgument is /// present and map pattern is empty (to ensure that we have no set pattern) diff --git a/LanguageFeatures/Patterns/map_A03_t01.dart b/LanguageFeatures/Patterns/map_A03_t01.dart index b5ca9abf22..6a9ba3f12a 100644 --- a/LanguageFeatures/Patterns/map_A03_t01.dart +++ b/LanguageFeatures/Patterns/map_A03_t01.dart @@ -5,33 +5,14 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: -/// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// /// @description Check that it is a compile-time error if any of the entry key /// expressions are not constant expressions. diff --git a/LanguageFeatures/Patterns/map_A04_t01.dart b/LanguageFeatures/Patterns/map_A04_t01.dart index fcdf8e811c..8876bbf597 100644 --- a/LanguageFeatures/Patterns/map_A04_t01.dart +++ b/LanguageFeatures/Patterns/map_A04_t01.dart @@ -5,153 +5,102 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. -/// -/// @description Check that it is a compile-time error if any two keys in the -/// map pattern are identical +/// @description Check that it is no error if any two keys in the map pattern +/// are identical /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns +import "../../Utils/expect.dart"; + class C { const C(); } -const c1 = C(); -const c2 = C(); - String test1(Map map) { return switch (map) { - {const C(): 1, const C(): 2} => "", -// ^^^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified - {1: 1, 1: 2} => "", -// ^ -// [analyzer] unspecified -// [cfe] unspecified - {c1: var a1, c2: final b1} => "", -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - {3.14: var a2, 3.14: final b2} => "", -// ^^^^ -// [analyzer] unspecified -// [cfe] unspecified - {"x": var a3, "x": final b3} => "", -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified + {const C(): 1, const C(): 2} => "case-1", + {1: 1, 1: 2} => "case-2", + {3.14: var a2, 3.14: final b2} => "case-3", + {"x": final String a3, "x": var b3} => "case-4", _ => "default" }; } -void test2(Map map) { +String test2(Map map) { switch (map) { case {const C(): 1, const C(): 2}: -// ^^^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified - break; + return "case-1"; case {1: 1, 1: 2}: -// ^ -// [analyzer] unspecified -// [cfe] unspecified - break; - case {c1: var a1, c2: final b1}: -// ^^ -// [analyzer] unspecified -// [cfe] unspecified + return "case-2"; case {3.14: var a2, 3.14: final b2}: -// ^^^^ -// [analyzer] unspecified -// [cfe] unspecified - break; - case {"x": var a3, "x": final b3}: -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified - break; + return "case-3"; + case {"x": final String a3, "x": var b3}: + return "case-4"; + default: + return "default"; } } -void test3(Map map) { +String test3(Map map) { if (map case {const C(): 1, const C(): 2}) { -// ^^^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified + return "case-1"; } if (map case {1: 1, 1: 2}) { -// ^ -// [analyzer] unspecified -// [cfe] unspecified - } - if (map case {c1: var a1, c2: final b1}) { -// ^^ -// [analyzer] unspecified -// [cfe] unspecified + return "case-2"; } if (map case {3.14: var a2, 3.14: final b2}) { -// ^^^^ -// [analyzer] unspecified -// [cfe] unspecified + return "case-3"; } - if (map case {"x": var a3, "x": final b3}) { -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified + if (map case {"x": final String a3, "x": var b3}) { + return "case-4"; } + return "default"; } main() { - var {const C(): 1, const C(): 2} = {const C(): 1}; -// ^^^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified - var {1: 1, 1: 2} = {1: 2}; -// ^ -// [analyzer] unspecified -// [cfe] unspecified - final {c1: var a1, c2: final b1} = {c2: 2}; -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - final {3.14: var a2, 3.14: final b2} = {3.14: 1}; -// ^^^^ -// [analyzer] unspecified -// [cfe] unspecified - final {"x": var a3, "x": final b3} = {"x": 1}; -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified + var {const C(): x1, const C(): y1} = {const C(): 1}; + Expect.equals(1, x1); + Expect.equals(1, y1); + + var {1: x2, 1: y2} = {1: 2}; + Expect.equals(2, x2); + Expect.equals(2, y2); + + final {3.14: x3, 3.14: y3} = {3.14: 1}; + Expect.equals(1, x3); + Expect.equals(1, y3); + + Expect.equals("default", test1({const C(): 1})); + Expect.equals("default", test1({const C(): 2})); + Expect.equals("default", test1({1: 1})); + Expect.equals("default", test1({1: 2})); + Expect.equals("case-3", test1({3.14: 1})); + Expect.equals("case-4", test1({"x": "y"})); + Expect.equals("default", test1({"x": 1})); + + Expect.equals("default", test2({const C(): 1})); + Expect.equals("default", test2({const C(): 2})); + Expect.equals("default", test2({1: 1})); + Expect.equals("default", test2({1: 2})); + Expect.equals("case-3", test2({3.14: 1})); + Expect.equals("case-4", test2({"x": "y"})); + Expect.equals("default", test2({"x": 1})); - test1({}); - test2({}); - test3({}); + Expect.equals("default", test3({const C(): 1})); + Expect.equals("default", test3({const C(): 2})); + Expect.equals("default", test3({1: 1})); + Expect.equals("default", test3({1: 2})); + Expect.equals("case-3", test3({3.14: 1})); + Expect.equals("case-4", test3({"x": "y"})); + Expect.equals("default", test3({"x": 1})); } diff --git a/LanguageFeatures/Patterns/map_A04_t02.dart b/LanguageFeatures/Patterns/map_A04_t02.dart index af9b1c2859..8956d57886 100644 --- a/LanguageFeatures/Patterns/map_A04_t02.dart +++ b/LanguageFeatures/Patterns/map_A04_t02.dart @@ -5,33 +5,14 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: -/// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// /// @description Check that it is no compile-time error if any two keys in the /// map are equal according to their == operator, but not identical diff --git a/LanguageFeatures/Patterns/map_A05_t01.dart b/LanguageFeatures/Patterns/map_A05_t01.dart index 2a3663491a..8ffa4e0e8f 100644 --- a/LanguageFeatures/Patterns/map_A05_t01.dart +++ b/LanguageFeatures/Patterns/map_A05_t01.dart @@ -5,128 +5,104 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. -/// -/// @description Check that it is a compile-time error if any two record keys -/// are equal +/// @description Check that it no error if any two record keys are equal /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns,records +import "../../Utils/expect.dart"; + String test1(Map map) { return switch (map) { - {(): 1, (): 2} => "", -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - {(1,): 1, (1,): 2} => "", -// ^^^^ -// [analyzer] unspecified -// [cfe] unspecified - {(n: 2): var a1, (n: 2): final b1} => "", -// ^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified - {(1, n: 2): var a2, (n:2, 1): final b2} => "", -// ^^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified + {(): 1, (): 2} => "case-1", + {(1,): 1, (1,): 2} => "case-2", + {(n: 2): var a1, (n: 2): final int b1} => "case-3", + {(1, n: 2): var a2, (n:2, 1): final int b2} => "case-4", _ => "default" }; } -void test2(Map map) { +String test2(Map map) { switch (map) { case {(): 1, (): 2}: -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - break; + return "case-1"; case {(1,): 1, (1,): 2}: -// ^^^^ -// [analyzer] unspecified -// [cfe] unspecified - break; - case {(n: 1): var a1, (n: 1): final b1}: -// ^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified - case {(1, n: 2): var a2, (n:2, 1): final b2}: -// ^^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified - break; + return "case-2"; + case {(n: 1): var a1, (n: 1): final int b1}: + return "case-3"; + case {(1, n: 2): var a2, (n:2, 1): final int b2}: + return "case-4"; + default: + return "default"; } } -void test3(Map map) { +String test3(Map map) { if (map case {(): 1, (): 2}) { -// ^^ -// [analyzer] unspecified -// [cfe] unspecified + return "case-1"; } if (map case {(1,): 1, (1,): 2}) { -// ^^^^ -// [analyzer] unspecified -// [cfe] unspecified + return "case-2"; } - if (map case {(n: 1): var a1, (n: 1): final b1}) { -// ^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified + if (map case {(n: 1): var a1, (n: 1): final int b1}) { + return "case-3"; } - if (map case {(1, n: 2): var a2, (n:2, 1): final b2}) { -// ^^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified + if (map case {(1, n: 2): var a2, (n:2, 1): final int b2}) { + return "case-4"; } + return "default"; } main() { - var {(): 1, (): 2} = {(): 1}; -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - var {(1,): 1, (1,): 2} = {(1,): 2}; -// ^^^^ -// [analyzer] unspecified -// [cfe] unspecified - final {(n: 1): var a1, (n: 1): final b1} = {(n: 1): 2}; -// ^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified - final {(1, n: 2): var a2, (n: 2, 1): final b2} = {(1, n: 2): 1}; -// ^^^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified + var {(): x1, (): y1} = {(): 1}; + Expect.equals(1, x1); + Expect.equals(1, y1); + + var {(1,): x2, (1,): y2} = {(1,): 2}; + Expect.equals(2, x2); + Expect.equals(2, y2); + + final {(n: 1): x3, (n: 1): y3} = {(n: 1): 2}; + Expect.equals(2, x3); + Expect.equals(2, y3); + + final {(1, n: 2): x4, (n: 2, 1): y4} = {(1, n: 2): 1}; + Expect.equals(1, x4); + Expect.equals(1, y4); + + Expect.equals("default", test1({(): 1})); + Expect.equals("default", test1({(): 2})); + Expect.equals("default", test1({(1,): 1})); + Expect.equals("default", test1({(1,): 2})); + Expect.equals("case-3", test1({(n: 1): 1})); + Expect.equals("default", test1({(n: 1): "2"})); + Expect.equals("case-4", test1({(1, n: 2): 1})); + Expect.equals("default", test1({(1, n: 2): "2"})); + + Expect.equals("default", test2({(): 1})); + Expect.equals("default", test2({(): 2})); + Expect.equals("default", test2({(1,): 1})); + Expect.equals("default", test2({(1,): 2})); + Expect.equals("case-3", test2({(n: 1): 1})); + Expect.equals("default", test2({(n: 1): "2"})); + Expect.equals("case-4", test2({(1, n: 2): 1})); + Expect.equals("default", test2({(1, n: 2): "2"})); - test1({}); - test2({}); - test3({}); + Expect.equals("default", test3({(): 1})); + Expect.equals("default", test3({(): 2})); + Expect.equals("default", test3({(1,): 1})); + Expect.equals("default", test3({(1,): 2})); + Expect.equals("case-3", test3({(n: 1): 1})); + Expect.equals("default", test3({(n: 1): "2"})); + Expect.equals("case-4", test3({(1, n: 2): 1})); + Expect.equals("default", test3({(1, n: 2): "2"})); } diff --git a/LanguageFeatures/Patterns/map_A06_t01.dart b/LanguageFeatures/Patterns/map_A06_t01.dart index d9e615a23c..7f2b0eb78e 100644 --- a/LanguageFeatures/Patterns/map_A06_t01.dart +++ b/LanguageFeatures/Patterns/map_A06_t01.dart @@ -5,44 +5,25 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. -/// -/// @description Check that it is a compile-time error if there is more than one -/// ... element in the map pattern. +/// @description Check that it is a compile-time error if rest element presents +/// in a map pattern. /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns String test1(Map map) { return switch (map) { - {1: 1, ..., ...} => "", -// ^^^ + {1: 1, ...} => "", +// ^^^ // [analyzer] unspecified // [cfe] unspecified _ => "default" @@ -51,29 +32,29 @@ String test1(Map map) { void test2(Map map) { switch (map) { - case {3: 4, ..., ...}: -// ^^^ + case {3: 4, ..., 5: 6}: +// ^^^ // [analyzer] unspecified // [cfe] unspecified } } void test3(Map map) { - if (map case {1: _, 2: _, ..., ...}) { -// ^^^ + if (map case {..., 1: _, 2: _}) { +// ^^^ // [analyzer] unspecified // [cfe] unspecified } } main() { - var {1: a, 2: b, ..., ...} = {1: 1, 2: 2, 3: 3, 4: 4}; -// ^^^ + var {1: a, 2: b, ...} = {1: 1, 2: 2, 3: 3, 4: 4}; +// ^^^ // [analyzer] unspecified // [cfe] unspecified - final {..., ...} = {1: 1, 2: 2, 3: 3, 4: 4}; -// ^^^ + final {...} = {1: 1, 2: 2, 3: 3, 4: 4}; +// ^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/map_A07_t01.dart b/LanguageFeatures/Patterns/map_A07_t01.dart index 4ecda83499..6d1dcad66d 100644 --- a/LanguageFeatures/Patterns/map_A07_t01.dart +++ b/LanguageFeatures/Patterns/map_A07_t01.dart @@ -5,79 +5,95 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' +/// mapPatternEntry ::= expression ':' pattern /// /// A map pattern matches values that implement Map and accesses values by key /// from it. -/// /// It is a compile-time error if: +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// -/// typeArguments is present and there are more or fewer than two type arguments -/// -/// Any of the entry key expressions are not constant expressions. -/// -/// If any two keys in the map are identical. Map patterns that don't have a -/// rest element only match if the length of the map is equal to the number of -/// map entries. If a map pattern has multiple identical key entries, they will -/// increase the required length for the pattern to match but in all but the -/// most perverse Map implementations will represent the same key. Thus, it's -/// very unlikely that any map pattern containing identical keys (and no rest -/// element) will ever match. Duplicate keys are most likely a typo in the code. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// There is more than one ... element in the map pattern. -/// -/// The ... element is not the last element in the map pattern. -/// -/// @description Check that it is a compile-time error if the ... element is not -/// the last element in the map pattern. +/// @description Check that if a map has more elements than number of +/// subpatterns in a map pattern then match may happen /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns +import "../../Utils/expect.dart"; + String test1(Map map) { return switch (map) { - {1: 1, ..., 2: 2} => "", -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified + {1: 1, 2: > 0} => "case-1", + {1: 2, 2: <= 0} => "case-2", + {1: 3, 2: var a} => "case-3", _ => "default" }; } -void test2(Map map) { +String test2(Map map) { switch (map) { - case {3: 4, ..., 5: 6}: -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified + case {1: 1, 2: > 0}: + return "case-1"; + case {1: 2, 2: <= 0}: + return "case-2"; + case {1: 3, 2: var a}: + return "case-3"; + default: + return "default"; } } -void test3(Map map) { - if (map case {1: _, 2: _, ..., 3: _}) { -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified +String test3(Map map) { + if (map case {1: 1, 2: > 0}) { + return "case-1"; + } + if (map case {1: 2, 2: <= 0}) { + return "case-2"; + } + if (map case {1: 3, 2: var a}) { + return "case-3"; } + return "default"; } main() { - var {1: a, 2: b, ..., 4: 4} = {1: 1, 2: 2, 3: 3, 4: 4}; -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified + var {1: a, 2: b} = {1: 1, 2: 2, 3: 3}; + Expect.equals(1, a); + Expect.equals(2, b); + + final {1: _, 2: int c} = {1: 2, 2: 2, 3: 3}; + Expect.equals(2, c); + + var {1: _, 2: _} = {1: 3, 2: 2, 3: 3}; + + Expect.equals("case-1", test1({1: 1, 2: 1})); + Expect.equals("case-1", test1({1: 1, 2: 2, 3: 3})); + Expect.equals("default", test1({1: 1})); + Expect.equals("case-2", test1({1: 2, 2: 0})); + Expect.equals("case-2", test1({1: 2, 2: -1, 3: 3})); + Expect.equals("default", test1({2: 0})); + Expect.equals("case-3", test1({1: 3, 2: 0})); + Expect.equals("case-3", test1({1: 3, 2: -1, 3: 3})); + Expect.equals("default", test1({1: 3})); - final {..., 4: 4} = {1: 1, 2: 2, 3: 3, 4: 4}; -// ^^^ -// [analyzer] unspecified -// [cfe] unspecified + Expect.equals("case-1", test2({1: 1, 2: 1})); + Expect.equals("case-1", test2({1: 1, 2: 2, 3: 3})); + Expect.equals("default", test2({1: 1})); + Expect.equals("case-2", test2({1: 2, 2: 0})); + Expect.equals("case-2", test2({1: 2, 2: -1, 3: 3})); + Expect.equals("default", test2({2: 0})); + Expect.equals("case-3", test2({1: 3, 2: 0})); + Expect.equals("case-3", test2({1: 3, 2: -1, 3: 3})); + Expect.equals("default", test2({1: 3})); - test1({}); - test2({}); - test3({}); + Expect.equals("case-1", test3({1: 1, 2: 1})); + Expect.equals("case-1", test3({1: 1, 2: 2, 3: 3})); + Expect.equals("default", test3({1: 1})); + Expect.equals("case-2", test3({1: 2, 2: 0})); + Expect.equals("case-2", test3({1: 2, 2: -1, 3: 3})); + Expect.equals("default", test3({2: 0})); + Expect.equals("case-3", test3({1: 3, 2: 0})); + Expect.equals("case-3", test3({1: 3, 2: -1, 3: 3})); + Expect.equals("default", test3({1: 3})); } diff --git a/LanguageFeatures/Patterns/map_A08_t01.dart b/LanguageFeatures/Patterns/map_A08_t01.dart index 43c63190d2..075a4ed8d0 100644 --- a/LanguageFeatures/Patterns/map_A08_t01.dart +++ b/LanguageFeatures/Patterns/map_A08_t01.dart @@ -5,101 +5,80 @@ /// @assertion /// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' /// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' -/// ... -/// Like lists, map patterns can also have a rest pattern. However, there's no -/// well-defined notion of a map "minus" some set of matched entries. Thus, the -/// rest pattern doesn't allow a subpattern to capture the "remaining" entries. +/// mapPatternEntry ::= expression ':' pattern /// -/// Also, there is no ordering to entries in a map, so we only allow the ... to -/// appear as the last element. Appearing anywhere else would send a confusing, -/// meaningless signal. +/// A map pattern matches values that implement Map and accesses values by key +/// from it. +/// It is a compile-time error if: +/// - typeArguments is present and there are more or fewer than two type +/// arguments. +/// - Any of the entry key expressions are not constant expressions. /// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// @description Check that if rest pattern is present then map, that has more -/// elements than number of subpatterns in a map pattern, may match +/// @description Check that an empty map pattern is a compile-time error /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns -import "../../Utils/expect.dart"; - String test1(Map map) { return switch (map) { - {1: 1, 2: > 0, ...} => "case-1", - {1: 2, 2: <= 0, ...} => "case-2", - {1: 3, 2: var a, ...} => "case-3", + {} => "case-1", +// ^ +// [analyzer] unspecified +// [cfe] unspecified + {} => "case-2", +// ^ +// [analyzer] unspecified +// [cfe] unspecified _ => "default" }; } String test2(Map map) { switch (map) { - case {1: 1, 2: > 0, ...}: + case {}: +// ^ +// [analyzer] unspecified +// [cfe] unspecified + return "case-1"; - case {1: 2, 2: <= 0, ...}: + case {}: +// ^ +// [analyzer] unspecified +// [cfe] unspecified + return "case-2"; - case {1: 3, 2: var a, ...}: - return "case-3"; default: return "default"; } } String test3(Map map) { - if (map case {1: 1, 2: > 0, ...}) { + if (map case {}) { +// ^ +// [analyzer] unspecified +// [cfe] unspecified return "case-1"; } - if (map case {1: 2, 2: <= 0, ...}) { + if (map case {}) { +// ^ +// [analyzer] unspecified +// [cfe] unspecified return "case-2"; } - if (map case {1: 3, 2: var a, ...}) { - return "case-3"; - } return "default"; } main() { - var {1: a, 2: b, ...} = {1: 1, 2: 2, 3: 3}; - Expect.equals(1, a); - Expect.equals(2, b); - - final {1: _, 2: int c, ...} = {1: 2, 2: 2, 3: 3}; - Expect.equals(2, c); - - var {1: _, 2: _, ...} = {1: 3, 2: 2, 3: 3}; - - Expect.equals("case-1", test1({1: 1, 2: 1})); - Expect.equals("case-1", test1({1: 1, 2: 2, 3: 3})); - Expect.equals("default", test1({1: 1})); - Expect.equals("case-2", test1({1: 2, 2: 0})); - Expect.equals("case-2", test1({1: 2, 2: -1, 3: 3})); - Expect.equals("default", test1({2: 0})); - Expect.equals("case-3", test1({1: 3, 2: 0})); - Expect.equals("case-3", test1({1: 3, 2: -1, 3: 3})); - Expect.equals("default", test1({1: 3})); - - Expect.equals("case-1", test2({1: 1, 2: 1})); - Expect.equals("case-1", test2({1: 1, 2: 2, 3: 3})); - Expect.equals("default", test2({1: 1})); - Expect.equals("case-2", test2({1: 2, 2: 0})); - Expect.equals("case-2", test2({1: 2, 2: -1, 3: 3})); - Expect.equals("default", test2({2: 0})); - Expect.equals("case-3", test2({1: 3, 2: 0})); - Expect.equals("case-3", test2({1: 3, 2: -1, 3: 3})); - Expect.equals("default", test2({1: 3})); + var {} = {}; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + final {} = {}; +// ^ +// [analyzer] unspecified +// [cfe] unspecified - Expect.equals("case-1", test3({1: 1, 2: 1})); - Expect.equals("case-1", test3({1: 1, 2: 2, 3: 3})); - Expect.equals("default", test3({1: 1})); - Expect.equals("case-2", test3({1: 2, 2: 0})); - Expect.equals("case-2", test3({1: 2, 2: -1, 3: 3})); - Expect.equals("default", test3({2: 0})); - Expect.equals("case-3", test3({1: 3, 2: 0})); - Expect.equals("case-3", test3({1: 3, 2: -1, 3: 3})); - Expect.equals("default", test3({1: 3})); + test1({}); + test2({}); + test3({}); } diff --git a/LanguageFeatures/Patterns/map_A08_t02.dart b/LanguageFeatures/Patterns/map_A08_t02.dart deleted file mode 100644 index bdee83591b..0000000000 --- a/LanguageFeatures/Patterns/map_A08_t02.dart +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// @assertion -/// mapPattern ::= typeArguments? '{' mapPatternEntries? '}' -/// mapPatternEntries ::= mapPatternEntry ( ',' mapPatternEntry )* ','? -/// mapPatternEntry ::= expression ':' pattern | '...' -/// ... -/// Like lists, map patterns can also have a rest pattern. However, there's no -/// well-defined notion of a map "minus" some set of matched entries. Thus, the -/// rest pattern doesn't allow a subpattern to capture the "remaining" entries. -/// -/// Also, there is no ordering to entries in a map, so we only allow the ... to -/// appear as the last element. Appearing anywhere else would send a confusing, -/// meaningless signal. -/// -/// Any two record keys which both have primitive == are equal. Since records -/// don't have defined identity, we can't use the previous rule to detect -/// identical records. But records do support an equality test known at compile -/// time if all of their fields do, so we use that. -/// -/// @description Check that it is a compile-time error if rest pattern of a map -/// declares a variable -/// @author sgrekhov22@gmail.com - -// SharedOptions=--enable-experiment=patterns - -String test1(Map map) { - return switch (map) { - {1: 1, 2: > 0, ...r1} => "case-1", -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - {1: 2, 2: <= 0, ... var r2} => "case-2", -// ^ -// [analyzer] unspecified -// [cfe] unspecified - {1: 3, 2: var a, ... final r3} => "case-3", -// ^ -// [analyzer] unspecified -// [cfe] unspecified - {1: 3, 2: var a, ... Map r4} => "case-4", -// ^ -// [analyzer] unspecified -// [cfe] unspecified - {1: 3, 2: var a, ... _} => "case-5", -// ^ -// [analyzer] unspecified -// [cfe] unspecified - _ => "default" - }; -} - -String test2(Map map) { - switch (map) { - case {1: 1, 2: > 0, ...r1}: return "case-1"; -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - case {1: 2, 2: <= 0, ... var r2}: return "case-2"; -// ^ -// [analyzer] unspecified -// [cfe] unspecified - case {1: 3, 2: var a, ...final r3}: return "case-3"; -// ^ -// [analyzer] unspecified -// [cfe] unspecified - case {1: 3, 2: var a, ...Map r4}: return "case-4"; -// ^ -// [analyzer] unspecified -// [cfe] unspecified - case {1: 3, 2: var a, ... _}: return "case-5"; -// ^ -// [analyzer] unspecified -// [cfe] unspecified - default: - return "default"; - } -} - -String test3(Map map) { - if (map case {1: 1, 2: > 0, ...r1}) { -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - return "case-1"; - } - if (map case {1: 2, 2: <= 0, ... var r2}) { -// ^ -// [analyzer] unspecified -// [cfe] unspecified - return "case-2"; - } - if (map case {1: 3, 2: var a, ...final r3}) { -// ^ -// [analyzer] unspecified -// [cfe] unspecified - return "case-3"; - } - if (map case {1: 3, 2: var a, ...Map r4}) { -// ^ -// [analyzer] unspecified -// [cfe] unspecified - return "case-3"; - } - if (map case {1: 3, 2: var a, ... _}) { -// ^ -// [analyzer] unspecified -// [cfe] unspecified - return "case-3"; - } - return "default"; -} - -main() { - var {1: a, 2: b, ...r1} = {1: 1, 2: 2, 3: 3}; -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - - final {1: 2, 2: int c, ...r2} = {1: 2, 2: 2, 3: 3}; -// ^^ -// [analyzer] unspecified -// [cfe] unspecified - - var {1: 3, 2: _, ...Map r3} = {1: 3, 2: 2, 3: 3}; -// ^ -// [analyzer] unspecified -// [cfe] unspecified - - final {1: 2, 2: int c, ..._} = {1: 2, 2: 2, 3: 3}; -// ^ -// [analyzer] unspecified -// [cfe] unspecified - - test1({}); - test2({}); - test3({}); -} diff --git a/LanguageFeatures/Patterns/matching_map_A01_t01.dart b/LanguageFeatures/Patterns/matching_map_A01_t01.dart index a9f34a01b9..6822b9f437 100644 --- a/LanguageFeatures/Patterns/matching_map_A01_t01.dart +++ b/LanguageFeatures/Patterns/matching_map_A01_t01.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,7 +42,7 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// /// @description Checks that if the runtime type of `v` is not a subtype of the /// required type of `p` then the match fails and no any member of `v` is called diff --git a/LanguageFeatures/Patterns/matching_map_A02_t01.dart b/LanguageFeatures/Patterns/matching_map_A02_t01.dart index 603bb639ef..dd9a4ae3f6 100644 --- a/LanguageFeatures/Patterns/matching_map_A02_t01.dart +++ b/LanguageFeatures/Patterns/matching_map_A02_t01.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,20 +42,23 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that if `p` has a rest element and `n == 0` (`n` is the -/// number of non-rest elements), then `length` is not called. +/// @description Checks that for each entry in `p`, in source order, if +/// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then +/// the map does not match. Test that in case of non-nullable `V` if +/// `v[k] == null` `containsKey(k)` is not called /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns +// Requirements=nnbd-strong import "patterns_collections_lib.dart"; import "../../Utils/expect.dart"; String test1(Object o) { switch (o) { - case {...}: + case {"key1": 1, "key2": 2}: return "match"; default: return "no match"; @@ -74,7 +66,7 @@ String test1(Object o) { } String test2(Object o) { - if (o case {...}) { + if (o case {"key1": 1, "key2": 2}) { return "match"; } return "no match"; @@ -82,22 +74,30 @@ String test2(Object o) { String test3(Object o) { return switch (o) { - {...} => "match", + {"key1": 1, "key2": 2} => "match", _ => "no match" }; } main() { - final map = MyMap({"key1": 42}); - Expect.equals("match", test1(map)); - Expect.equals("", map.log); - Expect.equals("match", test2(map)); - Expect.equals("", map.log); - Expect.equals("match", test3(map)); - Expect.equals("", map.log); + final map = MyMap({"key1": 1, "keyX": 42}); + Expect.equals("no match", test1(map)); + Expect.equals("[key1];[key2];", map.log); + map.clearLog(); + Expect.equals("no match", test2(map)); + Expect.equals("[key1];[key2];", map.log); + map.clearLog(); + Expect.equals("no match", test3(map)); + Expect.equals("[key1];[key2];", map.log); + map.clearLog(); - var {...} = map; - Expect.equals("", map.log); - final {...} = map; - Expect.equals("", map.log); + Expect.throws(() { + var {"key1": v1, "key2": v2} = map; + }); + Expect.equals("[key1];[key2];", map.log); + map.clearLog(); + Expect.throws(() { + final {"key1": v1, "key2": v2} = map; + }); + Expect.equals("[key1];[key2];", map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A02_t02.dart b/LanguageFeatures/Patterns/matching_map_A02_t02.dart index e96b224b60..073942bcb0 100644 --- a/LanguageFeatures/Patterns/matching_map_A02_t02.dart +++ b/LanguageFeatures/Patterns/matching_map_A02_t02.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,21 +42,23 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that if `p` has a rest element and `n > 0` (`n` is the -/// number of non-rest elements) and `l < n` ('l' is length of the `v`) then the -/// match fails and no elements of `v` are accessed via '[]' +/// @description Checks that for each entry in `p`, in source order, if +/// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then +/// the map does not match. Test that in case of non-nullable `V` +/// `containsKey(k)` is not called /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns +// Requirements=nnbd-strong import "patterns_collections_lib.dart"; import "../../Utils/expect.dart"; String test1(Object o) { switch (o) { - case {"key1": 1, "key2": 2, ...}: + case {"key1": _, "key2": _}: return "match"; default: return "no match"; @@ -75,7 +66,7 @@ String test1(Object o) { } String test2(Object o) { - if (o case {"key1": 1, "key2": 2, ...}) { + if (o case {"key1": _, "key2": _}) { return "match"; } return "no match"; @@ -83,30 +74,30 @@ String test2(Object o) { String test3(Object o) { return switch (o) { - {"key1": 1, "key2": 2, ...} => "match", + {"key1": _, "key2": _} => "match", _ => "no match" }; } main() { - final map = MyMap({"key1": 1}); + final map = MyMap({"key1": 1, "keyX": 42}); Expect.equals("no match", test1(map)); - Expect.equals("length;", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); Expect.equals("no match", test2(map)); - Expect.equals("length;", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); Expect.equals("no match", test3(map)); - Expect.equals("length;", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); Expect.throws(() { - var {"key1": v1, "key2": v2, ...} = map; + var {"key1": _, "key2": _} = map; }); - Expect.equals("length;", map.log); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); Expect.throws(() { - final {"key1": v1, "key2": v2, ...} = map; + final {"key1": _, "key2": _} = map; }); - Expect.equals("length;", map.log); + Expect.equals("[key1];[key2];", map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A02_t03.dart b/LanguageFeatures/Patterns/matching_map_A02_t03.dart index aaa97e4873..b36ce4c87e 100644 --- a/LanguageFeatures/Patterns/matching_map_A02_t03.dart +++ b/LanguageFeatures/Patterns/matching_map_A02_t03.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,21 +42,23 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that if `p` has no rest element, `n > 0` (`n` is the -/// number of non-rest elements) and `l != n` ('l' is length of the `v`) then -/// the match fails and no elements of `v` are accessed via '[]' +/// @description Checks that for each entry in `p`, in source order, if +/// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then +/// the map does not match. Test that if `V` is nullable and `v[k] == null` then +/// `v.containsKey(k)` is called /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns +// Requirements=nnbd-strong import "patterns_collections_lib.dart"; import "../../Utils/expect.dart"; String test1(Object o) { switch (o) { - case {"key1": 1, "key2": 2}: + case {"key1": 1, "key2": 2}: return "match"; default: return "no match"; @@ -75,7 +66,7 @@ String test1(Object o) { } String test2(Object o) { - if (o case {"key1": 1, "key2": 2}) { + if (o case {"key1": 1, "key2": 2}) { return "match"; } return "no match"; @@ -83,46 +74,30 @@ String test2(Object o) { String test3(Object o) { return switch (o) { - {"key1": 1, "key2": 2} => "match", + {"key1": 1, "key2": 2} => "match", _ => "no match" }; } main() { - final map1 = MyMap({"key1": 1}); - final map2 = MyMap({ - "key1": 1, - "key2": 2, - "key3": 3 - }); - - Expect.equals("no match", test1(map1)); - Expect.equals("length;", map1.log); - Expect.equals("no match", test1(map2)); - Expect.equals("length;", map2.log); - map1.clearLog(); - map2.clearLog(); - - Expect.equals("no match", test2(map1)); - Expect.equals("length;", map1.log); - Expect.equals("no match", test2(map2)); - Expect.equals("length;", map2.log); - map1.clearLog(); - map2.clearLog(); - - Expect.equals("no match", test3(map1)); - Expect.equals("length;", map1.log); - Expect.equals("no match", test3(map2)); - Expect.equals("length;", map2.log); - map1.clearLog(); - map2.clearLog(); + final map = MyMap({"key1": null, "keyX": 42}); + Expect.equals("no match", test1(map)); + Expect.equals("[key1];containsKey(key1);", map.log); + map.clearLog(); + Expect.equals("no match", test2(map)); + Expect.equals("[key1];containsKey(key1);", map.log); + map.clearLog(); + Expect.equals("no match", test3(map)); + Expect.equals("[key1];containsKey(key1);", map.log); + map.clearLog(); Expect.throws(() { - var {"key1": v1, "key2": v2} = map1; + var {"key1": v1, "key2": v2} = map; }); - Expect.equals("length;", map1.log); + Expect.equals("[key1];containsKey(key1);", map.log); + map.clearLog(); Expect.throws(() { - final {"key1": v1, "key2": v2} = map2; + final {"key1": v1, "key2": v2} = map; }); - Expect.equals("length;", map2.log); + Expect.equals("[key1];containsKey(key1);", map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A02_t04.dart b/LanguageFeatures/Patterns/matching_map_A02_t04.dart index f6875f6db0..502f792e3f 100644 --- a/LanguageFeatures/Patterns/matching_map_A02_t04.dart +++ b/LanguageFeatures/Patterns/matching_map_A02_t04.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,20 +42,23 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that if `p` is empty and `l > 0` ('l' is length of the -/// `v`) then the match fails and no elements of `v` are accessed via '[]' +/// @description Checks that for each entry in `p`, in source order, if +/// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then +/// the map does not match. Test that if `V` is nullable and `v[k] == null` then +/// `v.containsKey(k)` is called /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns +// Requirements=nnbd-strong import "patterns_collections_lib.dart"; import "../../Utils/expect.dart"; String test1(Object o) { switch (o) { - case {}: + case {"key1": _, "key2": _}: return "match"; default: return "no match"; @@ -74,7 +66,7 @@ String test1(Object o) { } String test2(Object o) { - if (o case {}) { + if (o case {"key1": _, "key2": _}) { return "match"; } return "no match"; @@ -82,30 +74,35 @@ String test2(Object o) { String test3(Object o) { return switch (o) { - {} => "match", + {"key1": _, "key2": _} => "match", _ => "no match" }; } main() { - final map = MyMap({"key1": 1}); + final map = MyMap({"key1": null, "keyX": 42}); Expect.equals("no match", test1(map)); - Expect.equals("length;", map.log); + Expect.equals("[key1];containsKey(key1);[key2];containsKey(key2);", + map.log); map.clearLog(); Expect.equals("no match", test2(map)); - Expect.equals("length;", map.log); + Expect.equals("[key1];containsKey(key1);[key2];containsKey(key2);", + map.log); map.clearLog(); Expect.equals("no match", test3(map)); - Expect.equals("length;", map.log); + Expect.equals("[key1];containsKey(key1);[key2];containsKey(key2);", + map.log); map.clearLog(); Expect.throws(() { - var {} = map; + var {"key1": _, "key2": _} = map; }); - Expect.equals("length;", map.log); + Expect.equals("[key1];containsKey(key1);[key2];containsKey(key2);", + map.log); map.clearLog(); Expect.throws(() { - final {} = map; + final {"key1": _, "key2": _} = map; }); - Expect.equals("length;", map.log); + Expect.equals("[key1];containsKey(key1);[key2];containsKey(key2);", + map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A03_t05.dart b/LanguageFeatures/Patterns/matching_map_A02_t05.dart similarity index 79% rename from LanguageFeatures/Patterns/matching_map_A03_t05.dart rename to LanguageFeatures/Patterns/matching_map_A02_t05.dart index c71f188142..daf1aab205 100644 --- a/LanguageFeatures/Patterns/matching_map_A03_t05.dart +++ b/LanguageFeatures/Patterns/matching_map_A02_t05.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,9 +42,9 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that for each non-rest entry in `p`, in source order, if +/// @description Checks that for each entry in `p`, in source order, if /// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then /// the map does not match. Test that if `V` is non-nullable and `v[k] == null` /// then `v.containsKey(k)` is not called @@ -93,22 +82,22 @@ String test3(Object o) { main() { final map = MyMap({"keyX": 0, "key2": 2}); Expect.equals("no match", test1(map)); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); map.clearLog(); Expect.equals("no match", test2(map)); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); map.clearLog(); Expect.equals("no match", test3(map)); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); map.clearLog(); Expect.throws(() { var {"key1": v1, "key2": v2} = map; }); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); map.clearLog(); Expect.throws(() { final {"key1": v1, "key2": v2} = map; }); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A03_t06.dart b/LanguageFeatures/Patterns/matching_map_A02_t06.dart similarity index 79% rename from LanguageFeatures/Patterns/matching_map_A03_t06.dart rename to LanguageFeatures/Patterns/matching_map_A02_t06.dart index c24db7278d..476fb1d908 100644 --- a/LanguageFeatures/Patterns/matching_map_A03_t06.dart +++ b/LanguageFeatures/Patterns/matching_map_A02_t06.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,9 +42,9 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that for each non-rest entry in `p`, in source order, if +/// @description Checks that for each entry in `p`, in source order, if /// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then /// the map does not match. Test that if `V` is non-nullable and `v[k] == null` /// then `v.containsKey(k)` is not called @@ -93,22 +82,22 @@ String test3(Object o) { main() { final map = MyMap({"keyX": 0, "key2": 2}); Expect.equals("no match", test1(map)); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); map.clearLog(); Expect.equals("no match", test2(map)); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); map.clearLog(); Expect.equals("no match", test3(map)); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); map.clearLog(); Expect.throws(() { var {"key1": _, "key2": _} = map; }); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); map.clearLog(); Expect.throws(() { final {"key1": _, "key2": _} = map; }); - Expect.equals("length;[key1];", map.log); + Expect.equals("[key1];", map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A03_t01.dart b/LanguageFeatures/Patterns/matching_map_A03_t01.dart index 54443240ee..f23dbd06d3 100644 --- a/LanguageFeatures/Patterns/matching_map_A03_t01.dart +++ b/LanguageFeatures/Patterns/matching_map_A03_t01.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,12 +42,9 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that for each non-rest entry in `p`, in source order, if -/// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then -/// the map does not match. Test that in case of non-nullable `V` if -/// `v[k] == null` `containsKey(k)` is not called +/// @description Checks that match succeeds if all entry subpatterns match /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns @@ -91,24 +77,20 @@ String test3(Object o) { } main() { - final map = MyMap({"key1": 1, "keyX": 42}); - Expect.equals("no match", test1(map)); - Expect.equals("length;[key1];[key2];", map.log); + final map = MyMap({"key1": 1, "key2": 2, "key3": 3}); + Expect.equals("match", test1(map)); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); - Expect.equals("no match", test2(map)); - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("match", test2(map)); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); - Expect.equals("no match", test3(map)); - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("match", test3(map)); + Expect.equals("[key1];[key2];", map.log); map.clearLog(); - Expect.throws(() { - var {"key1": v1, "key2": v2} = map; - }); - Expect.equals("length;[key1];[key2];", map.log); + var {"key1": x1, "key2": x2} = map; + Expect.equals("[key1];[key2];", map.log); map.clearLog(); - Expect.throws(() { - final {"key1": v1, "key2": v2} = map; - }); - Expect.equals("length;[key1];[key2];", map.log); + final {"key1": y1, "key2": y2} = map; + Expect.equals("[key1];[key2];", map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A03_t02.dart b/LanguageFeatures/Patterns/matching_map_A03_t02.dart index 1db24d79b1..229630f492 100644 --- a/LanguageFeatures/Patterns/matching_map_A03_t02.dart +++ b/LanguageFeatures/Patterns/matching_map_A03_t02.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,12 +42,9 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that for each non-rest entry in `p`, in source order, if -/// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then -/// the map does not match. Test that in case of non-nullable `V` -/// `containsKey(k)` is not called +/// @description Checks that match succeeds if all entry subpatterns match. /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns @@ -69,7 +55,7 @@ import "../../Utils/expect.dart"; String test1(Object o) { switch (o) { - case {"key1": _, "key2": _}: + case {"key1": 1, "key2": null}: return "match"; default: return "no match"; @@ -77,7 +63,7 @@ String test1(Object o) { } String test2(Object o) { - if (o case {"key1": _, "key2": _}) { + if (o case {"key1": 1, "key2": null}) { return "match"; } return "no match"; @@ -85,30 +71,26 @@ String test2(Object o) { String test3(Object o) { return switch (o) { - {"key1": _, "key2": _} => "match", + {"key1": 1, "key2": null} => "match", _ => "no match" }; } main() { - final map = MyMap({"key1": 1, "keyX": 42}); - Expect.equals("no match", test1(map)); - Expect.equals("length;[key1];[key2];", map.log); + final map = MyMap({"key1": 1, "key2": null}); + Expect.equals("match", test1(map)); + Expect.equals("[key1];[key2];containsKey(key2);", map.log); map.clearLog(); - Expect.equals("no match", test2(map)); - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("match", test2(map)); + Expect.equals("[key1];[key2];containsKey(key2);", map.log); map.clearLog(); - Expect.equals("no match", test3(map)); - Expect.equals("length;[key1];[key2];", map.log); + Expect.equals("match", test3(map)); + Expect.equals("[key1];[key2];containsKey(key2);", map.log); map.clearLog(); - Expect.throws(() { - var {"key1": _, "key2": _} = map; - }); - Expect.equals("length;[key1];[key2];", map.log); + var {"key1": x1, "key2": x2} = map; + Expect.equals("[key1];[key2];containsKey(key2);", map.log); map.clearLog(); - Expect.throws(() { - final {"key1": _, "key2": _} = map; - }); - Expect.equals("length;[key1];[key2];", map.log); + final {"key1": y1, "key2": y2} = map; + Expect.equals("[key1];[key2];containsKey(key2);", map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A03_t03.dart b/LanguageFeatures/Patterns/matching_map_A03_t03.dart index 2192de2fe6..97e1b2ba3b 100644 --- a/LanguageFeatures/Patterns/matching_map_A03_t03.dart +++ b/LanguageFeatures/Patterns/matching_map_A03_t03.dart @@ -17,18 +17,7 @@ /// Map: /// i. If the runtime type of v is not a subtype of the required type of p then /// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: +/// ii. For each entry in p, in source order: /// a. Evaluate the key expression to k. /// b. Evaluate v[k] to r. /// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then @@ -53,12 +42,9 @@ /// preserved. /// d. Else, match r against this entry's value subpattern. If it does not /// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. +/// iii. The match succeeds if all entry subpatterns match. /// -/// @description Checks that for each non-rest entry in `p`, in source order, if -/// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then -/// the map does not match. Test that if `V` is nullable and `v[k] == null` then -/// `v.containsKey(k)` is called +/// @description Checks that match succeeds if all entry subpatterns match. /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns @@ -69,7 +55,7 @@ import "../../Utils/expect.dart"; String test1(Object o) { switch (o) { - case {"key1": 1, "key2": 2}: + case {"key1": null}: return "match"; default: return "no match"; @@ -77,7 +63,7 @@ String test1(Object o) { } String test2(Object o) { - if (o case {"key1": 1, "key2": 2}) { + if (o case {"key1": null}) { return "match"; } return "no match"; @@ -85,30 +71,25 @@ String test2(Object o) { String test3(Object o) { return switch (o) { - {"key1": 1, "key2": 2} => "match", + {"key1": null} => "match", _ => "no match" }; } main() { - final map = MyMap({"key1": null, "keyX": 42}); - Expect.equals("no match", test1(map)); - Expect.equals("length;[key1];containsKey(key1);", map.log); + final map = MyMap({"key1": null, "key2": 42}); + Expect.equals("match", test1(map)); + Expect.equals("[key1];containsKey(key1);", map.log); map.clearLog(); - Expect.equals("no match", test2(map)); - Expect.equals("length;[key1];containsKey(key1);", map.log); + Expect.equals("match", test2(map)); + Expect.equals("[key1];containsKey(key1);", map.log); map.clearLog(); - Expect.equals("no match", test3(map)); - Expect.equals("length;[key1];containsKey(key1);", map.log); + Expect.equals("match", test3(map)); + Expect.equals("[key1];containsKey(key1);", map.log); map.clearLog(); - Expect.throws(() { - var {"key1": v1, "key2": v2} = map; - }); - Expect.equals("length;[key1];containsKey(key1);", map.log); - map.clearLog(); - Expect.throws(() { - final {"key1": v1, "key2": v2} = map; - }); - Expect.equals("length;[key1];containsKey(key1);", map.log); + var {...} = map; + Expect.equals("", map.log); + final {...} = map; + Expect.equals("", map.log); } diff --git a/LanguageFeatures/Patterns/matching_map_A03_t04.dart b/LanguageFeatures/Patterns/matching_map_A03_t04.dart deleted file mode 100644 index d949649152..0000000000 --- a/LanguageFeatures/Patterns/matching_map_A03_t04.dart +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// @assertion At runtime, a pattern is matched against a value. This determines -/// whether or not the match fails and the pattern refutes the value. If the -/// match succeeds, the pattern may also destructure data from the object or -/// bind variables. -/// -/// Refutable patterns usually occur in a context where match refutation causes -/// execution to skip over the body of code where any variables bound by the -/// pattern are in scope. If a pattern match failure occurs in an irrefutable -/// context, a runtime error is thrown. -/// -/// To match a pattern p against a value v: -/// ... -/// Map: -/// i. If the runtime type of v is not a subtype of the required type of p then -/// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: -/// a. Evaluate the key expression to k. -/// b. Evaluate v[k] to r. -/// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then -/// the map does not match. -/// Note: -/// - When v[k] returns a non-null value, we know the key is present and -/// we short-circuit the containsKey() call. -/// - If V is known to be a non-nullable type, then null is V is always -/// false and the expression simplifies to: -/// r != null -/// - Conversely, if V is known to be a nullable type, then null is V is -/// always true and the expression simplifies to: -/// r != null || v.containsKey(k) -/// - When V is a potentially nullable type, the null is V test must be -/// performed but can be hoisted out and shared across all entries since -/// it doesn't depend on k. -/// - If v is a poorly behaved Map whose v[k] and containsKey(k) results -/// don't agree (i.e. a non-null v[k] and false containsKey(k) or vice -/// versa) we do not detect that mismatch. Since badly behaved maps are -/// rare, this is allowed. Even if v is poorly behaved, a null value -/// will only be passed to the subpattern if null is V, so soundness is -/// preserved. -/// d. Else, match r against this entry's value subpattern. If it does not -/// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. -/// -/// @description Checks that for each non-rest entry in `p`, in source order, if -/// `v[k] != null || (null is V) && v.containsKey(k)` evaluates to `false` then -/// the map does not match. Test that if `V` is nullable and `v[k] == null` then -/// `v.containsKey(k)` is called -/// @author sgrekhov22@gmail.com - -// SharedOptions=--enable-experiment=patterns -// Requirements=nnbd-strong - -import "patterns_collections_lib.dart"; -import "../../Utils/expect.dart"; - -String test1(Object o) { - switch (o) { - case {"key1": _, "key2": _}: - return "match"; - default: - return "no match"; - } -} - -String test2(Object o) { - if (o case {"key1": _, "key2": _}) { - return "match"; - } - return "no match"; -} - -String test3(Object o) { - return switch (o) { - {"key1": _, "key2": _} => "match", - _ => "no match" - }; -} - -main() { - final map = MyMap({"key1": null, "keyX": 42}); - Expect.equals("no match", test1(map)); - Expect.equals("length;[key1];containsKey(key1);[key2];containsKey(key2);", - map.log); - map.clearLog(); - Expect.equals("no match", test2(map)); - Expect.equals("length;[key1];containsKey(key1);[key2];containsKey(key2);", - map.log); - map.clearLog(); - Expect.equals("no match", test3(map)); - Expect.equals("length;[key1];containsKey(key1);[key2];containsKey(key2);", - map.log); - map.clearLog(); - - Expect.throws(() { - var {"key1": _, "key2": _} = map; - }); - Expect.equals("length;[key1];containsKey(key1);[key2];containsKey(key2);", - map.log); - map.clearLog(); - Expect.throws(() { - final {"key1": _, "key2": _} = map; - }); - Expect.equals("length;[key1];containsKey(key1);[key2];containsKey(key2);", - map.log); -} diff --git a/LanguageFeatures/Patterns/matching_map_A04_t01.dart b/LanguageFeatures/Patterns/matching_map_A04_t01.dart deleted file mode 100644 index 4a7dd21614..0000000000 --- a/LanguageFeatures/Patterns/matching_map_A04_t01.dart +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// @assertion At runtime, a pattern is matched against a value. This determines -/// whether or not the match fails and the pattern refutes the value. If the -/// match succeeds, the pattern may also destructure data from the object or -/// bind variables. -/// -/// Refutable patterns usually occur in a context where match refutation causes -/// execution to skip over the body of code where any variables bound by the -/// pattern are in scope. If a pattern match failure occurs in an irrefutable -/// context, a runtime error is thrown. -/// -/// To match a pattern p against a value v: -/// ... -/// Map: -/// i. If the runtime type of v is not a subtype of the required type of p then -/// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: -/// a. Evaluate the key expression to k. -/// b. Evaluate v[k] to r. -/// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then -/// the map does not match. -/// Note: -/// - When v[k] returns a non-null value, we know the key is present and -/// we short-circuit the containsKey() call. -/// - If V is known to be a non-nullable type, then null is V is always -/// false and the expression simplifies to: -/// r != null -/// - Conversely, if V is known to be a nullable type, then null is V is -/// always true and the expression simplifies to: -/// r != null || v.containsKey(k) -/// - When V is a potentially nullable type, the null is V test must be -/// performed but can be hoisted out and shared across all entries since -/// it doesn't depend on k. -/// - If v is a poorly behaved Map whose v[k] and containsKey(k) results -/// don't agree (i.e. a non-null v[k] and false containsKey(k) or vice -/// versa) we do not detect that mismatch. Since badly behaved maps are -/// rare, this is allowed. Even if v is poorly behaved, a null value -/// will only be passed to the subpattern if null is V, so soundness is -/// preserved. -/// d. Else, match r against this entry's value subpattern. If it does not -/// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. -/// -/// @description Checks that match succeeds if all entry subpatterns match -/// @author sgrekhov22@gmail.com - -// SharedOptions=--enable-experiment=patterns -// Requirements=nnbd-strong - -import "patterns_collections_lib.dart"; -import "../../Utils/expect.dart"; - -String test1(Object o) { - switch (o) { - case {"key1": 1, "key2": 2}: - return "match"; - default: - return "no match"; - } -} - -String test2(Object o) { - if (o case {"key1": 1, "key2": 2}) { - return "match"; - } - return "no match"; -} - -String test3(Object o) { - return switch (o) { - {"key1": 1, "key2": 2} => "match", - _ => "no match" - }; -} - -main() { - final map = MyMap({"key1": 1, "key2": 2}); - Expect.equals("match", test1(map)); - Expect.equals("length;[key1];[key2];", map.log); - map.clearLog(); - Expect.equals("match", test2(map)); - Expect.equals("length;[key1];[key2];", map.log); - map.clearLog(); - Expect.equals("match", test3(map)); - Expect.equals("length;[key1];[key2];", map.log); - map.clearLog(); - - var {"key1": x1, "key2": x2} = map; - Expect.equals("length;[key1];[key2];", map.log); - map.clearLog(); - final {"key1": y1, "key2": y2} = map; - Expect.equals("length;[key1];[key2];", map.log); -} diff --git a/LanguageFeatures/Patterns/matching_map_A04_t02.dart b/LanguageFeatures/Patterns/matching_map_A04_t02.dart deleted file mode 100644 index 1fab39e602..0000000000 --- a/LanguageFeatures/Patterns/matching_map_A04_t02.dart +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// @assertion At runtime, a pattern is matched against a value. This determines -/// whether or not the match fails and the pattern refutes the value. If the -/// match succeeds, the pattern may also destructure data from the object or -/// bind variables. -/// -/// Refutable patterns usually occur in a context where match refutation causes -/// execution to skip over the body of code where any variables bound by the -/// pattern are in scope. If a pattern match failure occurs in an irrefutable -/// context, a runtime error is thrown. -/// -/// To match a pattern p against a value v: -/// ... -/// Map: -/// i. If the runtime type of v is not a subtype of the required type of p then -/// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: -/// a. Evaluate the key expression to k. -/// b. Evaluate v[k] to r. -/// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then -/// the map does not match. -/// Note: -/// - When v[k] returns a non-null value, we know the key is present and -/// we short-circuit the containsKey() call. -/// - If V is known to be a non-nullable type, then null is V is always -/// false and the expression simplifies to: -/// r != null -/// - Conversely, if V is known to be a nullable type, then null is V is -/// always true and the expression simplifies to: -/// r != null || v.containsKey(k) -/// - When V is a potentially nullable type, the null is V test must be -/// performed but can be hoisted out and shared across all entries since -/// it doesn't depend on k. -/// - If v is a poorly behaved Map whose v[k] and containsKey(k) results -/// don't agree (i.e. a non-null v[k] and false containsKey(k) or vice -/// versa) we do not detect that mismatch. Since badly behaved maps are -/// rare, this is allowed. Even if v is poorly behaved, a null value -/// will only be passed to the subpattern if null is V, so soundness is -/// preserved. -/// d. Else, match r against this entry's value subpattern. If it does not -/// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. -/// -/// @description Checks that match succeeds if all entry subpatterns match. -/// @author sgrekhov22@gmail.com - -// SharedOptions=--enable-experiment=patterns -// Requirements=nnbd-strong - -import "patterns_collections_lib.dart"; -import "../../Utils/expect.dart"; - -String test1(Object o) { - switch (o) { - case {"key1": 1, "key2": null}: - return "match"; - default: - return "no match"; - } -} - -String test2(Object o) { - if (o case {"key1": 1, "key2": null}) { - return "match"; - } - return "no match"; -} - -String test3(Object o) { - return switch (o) { - {"key1": 1, "key2": null} => "match", - _ => "no match" - }; -} - -main() { - final map = MyMap({"key1": 1, "key2": null}); - Expect.equals("match", test1(map)); - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); - map.clearLog(); - Expect.equals("match", test2(map)); - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); - map.clearLog(); - Expect.equals("match", test3(map)); - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); - map.clearLog(); - - var {"key1": x1, "key2": x2} = map; - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); - map.clearLog(); - final {"key1": y1, "key2": y2} = map; - Expect.equals("length;[key1];[key2];containsKey(key2);", map.log); -} diff --git a/LanguageFeatures/Patterns/matching_map_A04_t03.dart b/LanguageFeatures/Patterns/matching_map_A04_t03.dart deleted file mode 100644 index 61fb3d2e22..0000000000 --- a/LanguageFeatures/Patterns/matching_map_A04_t03.dart +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// @assertion At runtime, a pattern is matched against a value. This determines -/// whether or not the match fails and the pattern refutes the value. If the -/// match succeeds, the pattern may also destructure data from the object or -/// bind variables. -/// -/// Refutable patterns usually occur in a context where match refutation causes -/// execution to skip over the body of code where any variables bound by the -/// pattern are in scope. If a pattern match failure occurs in an irrefutable -/// context, a runtime error is thrown. -/// -/// To match a pattern p against a value v: -/// ... -/// Map: -/// i. If the runtime type of v is not a subtype of the required type of p then -/// the match fails. -/// ii. Let n be the number of non-rest elements. -/// iii. Check the length: -/// a. If p has a rest element and n == 0, then do nothing for checking the -/// length. -/// b. Else let l be the length of the map determined by calling length on v. -/// c. If p has a rest element (and n > 0): -/// a. If l < n then the match fails. -/// d. Else if n > 0 (and p has no rest element): -/// a. If l != n then the match fails. -/// e. Else p is empty: -/// a. If l > 0 then the match fails. -/// iv. For each non-rest entry in p, in source order: -/// a. Evaluate the key expression to k. -/// b. Evaluate v[k] to r. -/// c. If r != null || (null is V) && v.containsKey(k) evaluates to false then -/// the map does not match. -/// Note: -/// - When v[k] returns a non-null value, we know the key is present and -/// we short-circuit the containsKey() call. -/// - If V is known to be a non-nullable type, then null is V is always -/// false and the expression simplifies to: -/// r != null -/// - Conversely, if V is known to be a nullable type, then null is V is -/// always true and the expression simplifies to: -/// r != null || v.containsKey(k) -/// - When V is a potentially nullable type, the null is V test must be -/// performed but can be hoisted out and shared across all entries since -/// it doesn't depend on k. -/// - If v is a poorly behaved Map whose v[k] and containsKey(k) results -/// don't agree (i.e. a non-null v[k] and false containsKey(k) or vice -/// versa) we do not detect that mismatch. Since badly behaved maps are -/// rare, this is allowed. Even if v is poorly behaved, a null value -/// will only be passed to the subpattern if null is V, so soundness is -/// preserved. -/// d. Else, match r against this entry's value subpattern. If it does not -/// match, the map does not match. -/// v. The match succeeds if all entry subpatterns match. -/// -/// @description Checks that match succeeds if all entry subpatterns match. -/// @author sgrekhov22@gmail.com - -// SharedOptions=--enable-experiment=patterns -// Requirements=nnbd-strong - -import "patterns_collections_lib.dart"; -import "../../Utils/expect.dart"; - -String test1(Object o) { - switch (o) { - case {"key1": null,...}: - return "match"; - default: - return "no match"; - } -} - -String test2(Object o) { - if (o case {"key1": null,...}) { - return "match"; - } - return "no match"; -} - -String test3(Object o) { - return switch (o) { - {"key1": null,...} => "match", - _ => "no match" - }; -} - -main() { - final map = MyMap({"key1": null, "key2": 42}); - Expect.equals("match", test1(map)); - Expect.equals("length;[key1];containsKey(key1);", map.log); - map.clearLog(); - Expect.equals("match", test2(map)); - Expect.equals("length;[key1];containsKey(key1);", map.log); - map.clearLog(); - Expect.equals("match", test3(map)); - Expect.equals("length;[key1];containsKey(key1);", map.log); - map.clearLog(); - - var {...} = map; - Expect.equals("", map.log); - final {...} = map; - Expect.equals("", map.log); -} From 1180919aabb5779abd281e594e7d2283a66a8fb1 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Fri, 31 Mar 2023 10:43:32 +0300 Subject: [PATCH 2/7] Map identical keys rule changed --- LanguageFeatures/Patterns/map_A01_t01.dart | 2 + LanguageFeatures/Patterns/map_A01_t02.dart | 2 + LanguageFeatures/Patterns/map_A01_t03.dart | 2 + LanguageFeatures/Patterns/map_A01_t04.dart | 2 + LanguageFeatures/Patterns/map_A02_t01.dart | 2 + LanguageFeatures/Patterns/map_A02_t02.dart | 2 + LanguageFeatures/Patterns/map_A03_t01.dart | 2 + LanguageFeatures/Patterns/map_A04_t01.dart | 148 +++++++++++------- LanguageFeatures/Patterns/map_A04_t02.dart | 2 + LanguageFeatures/Patterns/map_A05_t01.dart | 137 ++++++++-------- LanguageFeatures/Patterns/map_A06_t01.dart | 2 + LanguageFeatures/Patterns/map_A07_t01.dart | 2 + LanguageFeatures/Patterns/map_A08_t01.dart | 2 + .../Patterns/matching_map_A01_t01.dart | 6 +- .../Patterns/matching_map_A01_t02.dart | 6 +- 15 files changed, 191 insertions(+), 128 deletions(-) diff --git a/LanguageFeatures/Patterns/map_A01_t01.dart b/LanguageFeatures/Patterns/map_A01_t01.dart index 150b5ab060..116b461025 100644 --- a/LanguageFeatures/Patterns/map_A01_t01.dart +++ b/LanguageFeatures/Patterns/map_A01_t01.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Checks a map pattern with different subpatterns in a switch /// expression diff --git a/LanguageFeatures/Patterns/map_A01_t02.dart b/LanguageFeatures/Patterns/map_A01_t02.dart index 071e2927b6..0f6c12f440 100644 --- a/LanguageFeatures/Patterns/map_A01_t02.dart +++ b/LanguageFeatures/Patterns/map_A01_t02.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Checks a map pattern with different subpatterns in a switch /// statement diff --git a/LanguageFeatures/Patterns/map_A01_t03.dart b/LanguageFeatures/Patterns/map_A01_t03.dart index 3ac12121b7..ddc093b821 100644 --- a/LanguageFeatures/Patterns/map_A01_t03.dart +++ b/LanguageFeatures/Patterns/map_A01_t03.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Checks a map pattern with different subpatterns in an if-case /// statement diff --git a/LanguageFeatures/Patterns/map_A01_t04.dart b/LanguageFeatures/Patterns/map_A01_t04.dart index 9c71c7f454..92079d2129 100644 --- a/LanguageFeatures/Patterns/map_A01_t04.dart +++ b/LanguageFeatures/Patterns/map_A01_t04.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Checks a map pattern in a declaration context /// @author sgrekhov22@gmail.com diff --git a/LanguageFeatures/Patterns/map_A02_t01.dart b/LanguageFeatures/Patterns/map_A02_t01.dart index 66f8ff513e..504595af4c 100644 --- a/LanguageFeatures/Patterns/map_A02_t01.dart +++ b/LanguageFeatures/Patterns/map_A02_t01.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Check that it is a compile-time error if typeArguments is /// present and there are more or fewer than two type arguments diff --git a/LanguageFeatures/Patterns/map_A02_t02.dart b/LanguageFeatures/Patterns/map_A02_t02.dart index c19d862c20..b2f577f547 100644 --- a/LanguageFeatures/Patterns/map_A02_t02.dart +++ b/LanguageFeatures/Patterns/map_A02_t02.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Check that it is a compile-time error if one typeArgument is /// present and map pattern is empty (to ensure that we have no set pattern) diff --git a/LanguageFeatures/Patterns/map_A03_t01.dart b/LanguageFeatures/Patterns/map_A03_t01.dart index 6a9ba3f12a..735a5f24a7 100644 --- a/LanguageFeatures/Patterns/map_A03_t01.dart +++ b/LanguageFeatures/Patterns/map_A03_t01.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Check that it is a compile-time error if any of the entry key /// expressions are not constant expressions. diff --git a/LanguageFeatures/Patterns/map_A04_t01.dart b/LanguageFeatures/Patterns/map_A04_t01.dart index 8876bbf597..441d0d3e66 100644 --- a/LanguageFeatures/Patterns/map_A04_t01.dart +++ b/LanguageFeatures/Patterns/map_A04_t01.dart @@ -13,94 +13,128 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// -/// @description Check that it is no error if any two keys in the map pattern -/// are identical +/// @description Check that it is a compile-time error if any two keys in the +/// map pattern are identical /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns -import "../../Utils/expect.dart"; - class C { const C(); } +const c1 = C(); +const c2 = C(); + String test1(Map map) { return switch (map) { - {const C(): 1, const C(): 2} => "case-1", - {1: 1, 1: 2} => "case-2", - {3.14: var a2, 3.14: final b2} => "case-3", - {"x": final String a3, "x": var b3} => "case-4", + {const C(): 1, const C(): 2} => "", +// ^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + {1: 1, 1: 2} => "", +// ^ +// [analyzer] unspecified +// [cfe] unspecified + {c1: var a1, c2: final b1} => "", +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + {3.14: var a2, 3.14: final b2} => "", +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + {"x": var a3, "x": final b3} => "", +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified _ => "default" }; } -String test2(Map map) { +void test2(Map map) { switch (map) { case {const C(): 1, const C(): 2}: - return "case-1"; +// ^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + break; case {1: 1, 1: 2}: - return "case-2"; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + break; + case {c1: var a1, c2: final b1}: +// ^^ +// [analyzer] unspecified +// [cfe] unspecified case {3.14: var a2, 3.14: final b2}: - return "case-3"; - case {"x": final String a3, "x": var b3}: - return "case-4"; - default: - return "default"; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + break; + case {"x": var a3, "x": final b3}: +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified + break; } } -String test3(Map map) { +void test3(Map map) { if (map case {const C(): 1, const C(): 2}) { - return "case-1"; +// ^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified } if (map case {1: 1, 1: 2}) { - return "case-2"; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + } + if (map case {c1: var a1, c2: final b1}) { +// ^^ +// [analyzer] unspecified +// [cfe] unspecified } if (map case {3.14: var a2, 3.14: final b2}) { - return "case-3"; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified } - if (map case {"x": final String a3, "x": var b3}) { - return "case-4"; + if (map case {"x": var a3, "x": final b3}) { +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified } - return "default"; } main() { - var {const C(): x1, const C(): y1} = {const C(): 1}; - Expect.equals(1, x1); - Expect.equals(1, y1); - - var {1: x2, 1: y2} = {1: 2}; - Expect.equals(2, x2); - Expect.equals(2, y2); - - final {3.14: x3, 3.14: y3} = {3.14: 1}; - Expect.equals(1, x3); - Expect.equals(1, y3); - - Expect.equals("default", test1({const C(): 1})); - Expect.equals("default", test1({const C(): 2})); - Expect.equals("default", test1({1: 1})); - Expect.equals("default", test1({1: 2})); - Expect.equals("case-3", test1({3.14: 1})); - Expect.equals("case-4", test1({"x": "y"})); - Expect.equals("default", test1({"x": 1})); - - Expect.equals("default", test2({const C(): 1})); - Expect.equals("default", test2({const C(): 2})); - Expect.equals("default", test2({1: 1})); - Expect.equals("default", test2({1: 2})); - Expect.equals("case-3", test2({3.14: 1})); - Expect.equals("case-4", test2({"x": "y"})); - Expect.equals("default", test2({"x": 1})); + var {const C(): 1, const C(): 2} = {const C(): 1}; +// ^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + var {1: 1, 1: 2} = {1: 2}; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + final {c1: var a1, c2: final b1} = {c2: 2}; +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + final {3.14: var a2, 3.14: final b2} = {3.14: 1}; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + final {"x": var a3, "x": final b3} = {"x": 1}; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified - Expect.equals("default", test3({const C(): 1})); - Expect.equals("default", test3({const C(): 2})); - Expect.equals("default", test3({1: 1})); - Expect.equals("default", test3({1: 2})); - Expect.equals("case-3", test3({3.14: 1})); - Expect.equals("case-4", test3({"x": "y"})); - Expect.equals("default", test3({"x": 1})); + test1({}); + test2({}); + test3({}); } diff --git a/LanguageFeatures/Patterns/map_A04_t02.dart b/LanguageFeatures/Patterns/map_A04_t02.dart index 8956d57886..ac8c25f6b4 100644 --- a/LanguageFeatures/Patterns/map_A04_t02.dart +++ b/LanguageFeatures/Patterns/map_A04_t02.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Check that it is no compile-time error if any two keys in the /// map are equal according to their == operator, but not identical diff --git a/LanguageFeatures/Patterns/map_A05_t01.dart b/LanguageFeatures/Patterns/map_A05_t01.dart index 8ffa4e0e8f..03648c6880 100644 --- a/LanguageFeatures/Patterns/map_A05_t01.dart +++ b/LanguageFeatures/Patterns/map_A05_t01.dart @@ -13,96 +13,103 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// -/// @description Check that it no error if any two record keys are equal +/// @description Check that it is a compile-time error if any two record keys +/// are equal /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns,records -import "../../Utils/expect.dart"; - String test1(Map map) { return switch (map) { - {(): 1, (): 2} => "case-1", - {(1,): 1, (1,): 2} => "case-2", - {(n: 2): var a1, (n: 2): final int b1} => "case-3", - {(1, n: 2): var a2, (n:2, 1): final int b2} => "case-4", + {(): 1, (): 2} => "", +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + {(1,): 1, (1,): 2} => "", +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + {(n: 2): var a1, (n: 2): final b1} => "", +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + {(1, n: 2): var a2, (n:2, 1): final b2} => "", +// ^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified _ => "default" }; } -String test2(Map map) { +void test2(Map map) { switch (map) { case {(): 1, (): 2}: - return "case-1"; +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + break; case {(1,): 1, (1,): 2}: - return "case-2"; - case {(n: 1): var a1, (n: 1): final int b1}: - return "case-3"; - case {(1, n: 2): var a2, (n:2, 1): final int b2}: - return "case-4"; - default: - return "default"; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + break; + case {(n: 1): var a1, (n: 1): final b1}: +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + case {(1, n: 2): var a2, (n:2, 1): final b2}: +// ^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + break; } } -String test3(Map map) { +void test3(Map map) { if (map case {(): 1, (): 2}) { - return "case-1"; +// ^^ +// [analyzer] unspecified +// [cfe] unspecified } if (map case {(1,): 1, (1,): 2}) { - return "case-2"; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified } - if (map case {(n: 1): var a1, (n: 1): final int b1}) { - return "case-3"; + if (map case {(n: 1): var a1, (n: 1): final b1}) { +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified } - if (map case {(1, n: 2): var a2, (n:2, 1): final int b2}) { - return "case-4"; + if (map case {(1, n: 2): var a2, (n:2, 1): final b2}) { +// ^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified } - return "default"; } main() { - var {(): x1, (): y1} = {(): 1}; - Expect.equals(1, x1); - Expect.equals(1, y1); - - var {(1,): x2, (1,): y2} = {(1,): 2}; - Expect.equals(2, x2); - Expect.equals(2, y2); - - final {(n: 1): x3, (n: 1): y3} = {(n: 1): 2}; - Expect.equals(2, x3); - Expect.equals(2, y3); - - final {(1, n: 2): x4, (n: 2, 1): y4} = {(1, n: 2): 1}; - Expect.equals(1, x4); - Expect.equals(1, y4); - - Expect.equals("default", test1({(): 1})); - Expect.equals("default", test1({(): 2})); - Expect.equals("default", test1({(1,): 1})); - Expect.equals("default", test1({(1,): 2})); - Expect.equals("case-3", test1({(n: 1): 1})); - Expect.equals("default", test1({(n: 1): "2"})); - Expect.equals("case-4", test1({(1, n: 2): 1})); - Expect.equals("default", test1({(1, n: 2): "2"})); - - Expect.equals("default", test2({(): 1})); - Expect.equals("default", test2({(): 2})); - Expect.equals("default", test2({(1,): 1})); - Expect.equals("default", test2({(1,): 2})); - Expect.equals("case-3", test2({(n: 1): 1})); - Expect.equals("default", test2({(n: 1): "2"})); - Expect.equals("case-4", test2({(1, n: 2): 1})); - Expect.equals("default", test2({(1, n: 2): "2"})); + var {(): 1, (): 2} = {(): 1}; +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + var {(1,): 1, (1,): 2} = {(1,): 2}; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + final {(n: 1): var a1, (n: 1): final b1} = {(n: 1): 2}; +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + final {(1, n: 2): var a2, (n: 2, 1): final b2} = {(1, n: 2): 1}; +// ^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified - Expect.equals("default", test3({(): 1})); - Expect.equals("default", test3({(): 2})); - Expect.equals("default", test3({(1,): 1})); - Expect.equals("default", test3({(1,): 2})); - Expect.equals("case-3", test3({(n: 1): 1})); - Expect.equals("default", test3({(n: 1): "2"})); - Expect.equals("case-4", test3({(1, n: 2): 1})); - Expect.equals("default", test3({(1, n: 2): "2"})); + test1({}); + test2({}); + test3({}); } diff --git a/LanguageFeatures/Patterns/map_A06_t01.dart b/LanguageFeatures/Patterns/map_A06_t01.dart index 7f2b0eb78e..1c4146b368 100644 --- a/LanguageFeatures/Patterns/map_A06_t01.dart +++ b/LanguageFeatures/Patterns/map_A06_t01.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Check that it is a compile-time error if rest element presents /// in a map pattern. diff --git a/LanguageFeatures/Patterns/map_A07_t01.dart b/LanguageFeatures/Patterns/map_A07_t01.dart index 6d1dcad66d..964e50186b 100644 --- a/LanguageFeatures/Patterns/map_A07_t01.dart +++ b/LanguageFeatures/Patterns/map_A07_t01.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Check that if a map has more elements than number of /// subpatterns in a map pattern then match may happen diff --git a/LanguageFeatures/Patterns/map_A08_t01.dart b/LanguageFeatures/Patterns/map_A08_t01.dart index 075a4ed8d0..4486ce8eae 100644 --- a/LanguageFeatures/Patterns/map_A08_t01.dart +++ b/LanguageFeatures/Patterns/map_A08_t01.dart @@ -13,6 +13,8 @@ /// - typeArguments is present and there are more or fewer than two type /// arguments. /// - Any of the entry key expressions are not constant expressions. +/// - Any two keys in the map are identical. +/// - Any two record keys which both have primitive equality are equal. /// /// @description Check that an empty map pattern is a compile-time error /// @author sgrekhov22@gmail.com diff --git a/LanguageFeatures/Patterns/matching_map_A01_t01.dart b/LanguageFeatures/Patterns/matching_map_A01_t01.dart index 1fc0b12302..6a4040435a 100644 --- a/LanguageFeatures/Patterns/matching_map_A01_t01.dart +++ b/LanguageFeatures/Patterns/matching_map_A01_t01.dart @@ -55,7 +55,7 @@ import "../../Utils/expect.dart"; String test1(Object o) { switch (o) { - case {...}: + case {"key1": _}: return "match-1"; case {"key1": _}: return "match-2"; @@ -65,7 +65,7 @@ String test1(Object o) { } String test2(Object o) { - if (o case {...}) { + if (o case {"key1": _}) { return "match-1"; } if (o case {"key1": _}) { @@ -76,7 +76,7 @@ String test2(Object o) { String test3(Object o) { return switch (o) { - {...} => "match-1", + {"key1": _} => "match-1", {"key1": _} => "match-2", _ => "no match" }; diff --git a/LanguageFeatures/Patterns/matching_map_A01_t02.dart b/LanguageFeatures/Patterns/matching_map_A01_t02.dart index 9398655089..25f5c71218 100644 --- a/LanguageFeatures/Patterns/matching_map_A01_t02.dart +++ b/LanguageFeatures/Patterns/matching_map_A01_t02.dart @@ -67,7 +67,7 @@ import "../../Utils/expect.dart"; String test1(Object o) { switch (o) { - case {...}: + case {"key1": _}: return "match-1"; case {"key1": _}: return "match-2"; @@ -77,7 +77,7 @@ String test1(Object o) { } String test2(Object o) { - if (o case {...}) { + if (o case {"key1": _}) { return "match-1"; } if (o case {"key1": _}) { @@ -88,7 +88,7 @@ String test2(Object o) { String test3(Object o) { return switch (o) { - {...} => "match-1", + {"key1": _} => "match-1", {"key1": _} => "match-2", _ => "no match" }; From 617e74bb84d238d0e23b7fd158132404d5fe5819 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Fri, 31 Mar 2023 12:38:27 +0300 Subject: [PATCH 3/7] More rest elements and empty maps found --- .../Patterns/if_case_A02_t01.dart | 2 +- .../Patterns/if_case_A02_t02.dart | 2 +- .../Patterns/if_case_A02_t03.dart | 2 +- .../Patterns/matching_map_A03_t03.dart | 5 -- .../Patterns/pattern_assignment_A01_t03.dart | 2 +- .../Patterns/pattern_assignment_A04_t03.dart | 6 +- .../Patterns/pattern_assignment_A05_t01.dart | 2 +- .../Patterns/pattern_assignment_A05_t02.dart | 2 +- .../Patterns/pattern_assignment_A05_t03.dart | 2 +- .../Patterns/pattern_assignment_A05_t04.dart | 2 +- .../Patterns/pattern_assignment_A05_t05.dart | 2 +- .../Patterns/pattern_assignment_A05_t06.dart | 2 +- .../Patterns/pattern_assignment_A06_t01.dart | 2 +- .../Patterns/pattern_assignment_A06_t02.dart | 2 +- .../Patterns/pattern_assignment_A06_t03.dart | 2 +- .../Patterns/pattern_assignment_A06_t04.dart | 2 +- .../Patterns/pattern_assignment_A07_t01.dart | 2 +- .../Patterns/pattern_assignment_A08_t01.dart | 2 +- .../Patterns/switch_statement_A01_t01.dart | 6 +- .../Patterns/type_inference_A08_t01.dart | 7 +-- .../Patterns/type_inference_A08_t02.dart | 41 ++++++++++-- .../Patterns/type_inference_A08_t03.dart | 62 ------------------- .../Patterns/type_inference_A29_t01.dart | 16 ++--- .../Patterns/type_inference_A29_t03.dart | 6 +- .../Patterns/type_inference_A29_t04.dart | 6 +- .../Patterns/type_inference_A29_t05.dart | 2 +- .../Patterns/type_inference_A29_t06.dart | 8 +-- .../Patterns/type_inference_A29_t07.dart | 8 +-- .../Patterns/type_inference_A29_t08.dart | 8 +-- .../Patterns/type_inference_A29_t09.dart | 6 +- .../Patterns/type_inference_A29_t10.dart | 2 +- .../Patterns/type_inference_A29_t11.dart | 8 +-- .../variable_declaration_A01_t01.dart | 2 +- .../variable_declaration_A01_t02.dart | 4 +- .../variable_declaration_A01_t03.dart | 4 +- .../variable_declaration_A01_t04.dart | 4 +- .../variable_declaration_A01_t05.dart | 4 +- .../variable_declaration_A01_t06.dart | 4 +- .../variable_declaration_A03_t05.dart | 4 +- .../variable_declaration_A03_t06.dart | 4 +- .../variable_declaration_A04_t05.dart | 4 +- .../variable_declaration_A04_t06.dart | 4 +- 42 files changed, 114 insertions(+), 153 deletions(-) delete mode 100644 LanguageFeatures/Patterns/type_inference_A08_t03.dart diff --git a/LanguageFeatures/Patterns/if_case_A02_t01.dart b/LanguageFeatures/Patterns/if_case_A02_t01.dart index 96fa2d09bb..b6df7d3638 100644 --- a/LanguageFeatures/Patterns/if_case_A02_t01.dart +++ b/LanguageFeatures/Patterns/if_case_A02_t01.dart @@ -95,7 +95,7 @@ List testMap1(Map map) { List testMap2(Map map) => [ 1, - if (map case {"key1": 1, "key2": final b, ...} when b < 0) 2 else 3, + if (map case {"key1": 1, "key2": final b} when b < 0) 2 else 3, 4 ]; diff --git a/LanguageFeatures/Patterns/if_case_A02_t02.dart b/LanguageFeatures/Patterns/if_case_A02_t02.dart index 03b4fd5ec1..eda9efddcf 100644 --- a/LanguageFeatures/Patterns/if_case_A02_t02.dart +++ b/LanguageFeatures/Patterns/if_case_A02_t02.dart @@ -163,7 +163,7 @@ Map testMap1(Map map) { Map testMap2(Map map) => { "key1": 1, - if (map case {"key1": 1, "key2": final b, ...} when b < 0) + if (map case {"key1": 1, "key2": final b} when b < 0) "key2": 2 else "key3": 3, diff --git a/LanguageFeatures/Patterns/if_case_A02_t03.dart b/LanguageFeatures/Patterns/if_case_A02_t03.dart index 98cf77fe40..d054cbe708 100644 --- a/LanguageFeatures/Patterns/if_case_A02_t03.dart +++ b/LanguageFeatures/Patterns/if_case_A02_t03.dart @@ -156,7 +156,7 @@ Set testMap1(Map map) { Set testMap2(Map map) => { 1, - if (map case {"key1": 1, "key2": final b, ...} when b < 0) 2 else 3, + if (map case {"key1": 1, "key2": final b} when b < 0) 2 else 3, 4 }; diff --git a/LanguageFeatures/Patterns/matching_map_A03_t03.dart b/LanguageFeatures/Patterns/matching_map_A03_t03.dart index 97e1b2ba3b..0a4bf0bccf 100644 --- a/LanguageFeatures/Patterns/matching_map_A03_t03.dart +++ b/LanguageFeatures/Patterns/matching_map_A03_t03.dart @@ -87,9 +87,4 @@ main() { Expect.equals("match", test3(map)); Expect.equals("[key1];containsKey(key1);", map.log); map.clearLog(); - - var {...} = map; - Expect.equals("", map.log); - final {...} = map; - Expect.equals("", map.log); } diff --git a/LanguageFeatures/Patterns/pattern_assignment_A01_t03.dart b/LanguageFeatures/Patterns/pattern_assignment_A01_t03.dart index 32be8ab36c..53519781fd 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A01_t03.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A01_t03.dart @@ -32,7 +32,7 @@ main() { Expect.equals(4, b2); int a3 = 42, b3 = 42; - {"key1": a3, "key2": b3, ...} = {"key1": 5, "key2": 6, "key3": 7}; + {"key1": a3, "key2": b3} = {"key1": 5, "key2": 6, "key3": 7}; Expect.equals(5, a3); Expect.equals(6, b3); } diff --git a/LanguageFeatures/Patterns/pattern_assignment_A04_t03.dart b/LanguageFeatures/Patterns/pattern_assignment_A04_t03.dart index 884d9c043d..6e5fb6a1aa 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A04_t03.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A04_t03.dart @@ -26,7 +26,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": int a, "key2": _, ...} = {"key1": 1, "key2": 2, "key3": 3}; + {"key1": int a, "key2": _} = {"key1": 1, "key2": 2, "key3": 3}; // ^^^ // [analyzer] unspecified // [cfe] unspecified @@ -41,7 +41,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": a, "key2": int b1, ...} = {"key1": 1, "key2": 2, "key3": 3}; + {"key1": a, "key2": int b1} = {"key1": 1, "key2": 2, "key3": 3}; // ^^^ // [analyzer] unspecified // [cfe] unspecified @@ -51,7 +51,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": const a, "key2": b, ...} = {"key1": 1, "key2": 2, "key3": 3}; + {"key1": const a, "key2": b} = {"key1": 1, "key2": 2, "key3": 3}; // ^^^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A05_t01.dart b/LanguageFeatures/Patterns/pattern_assignment_A05_t01.dart index 5cdd500aa5..a82f2a8cc6 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A05_t01.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A05_t01.dart @@ -60,7 +60,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": af, ...} = {"key1": 1, "key2": 2}; + {"key1": af} = {"key1": 1, "key2": 2}; // ^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A05_t02.dart b/LanguageFeatures/Patterns/pattern_assignment_A05_t02.dart index 5f51d2c1a4..d1de869c50 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A05_t02.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A05_t02.dart @@ -67,7 +67,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": af, ...} = {"key1": 1, "key2": 2}; + {"key1": af} = {"key1": 1, "key2": 2}; // ^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A05_t03.dart b/LanguageFeatures/Patterns/pattern_assignment_A05_t03.dart index 8127e8219c..4d474bb0de 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A05_t03.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A05_t03.dart @@ -60,7 +60,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": af, ...} = {"key1": 1, "key2": 2}; + {"key1": af} = {"key1": 1, "key2": 2}; // ^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A05_t04.dart b/LanguageFeatures/Patterns/pattern_assignment_A05_t04.dart index 7ebb7d6563..a69fb226fa 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A05_t04.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A05_t04.dart @@ -55,7 +55,7 @@ main() { {"key1": af3, "key2": _} = {"key1": 1, "key2": 2}; Expect.equals(1, af3); - {"key1": af4, ...} = {"key1": 1, "key2": 2}; + {"key1": af4} = {"key1": 1, "key2": 2}; Expect.equals(1, af4); (af5, _) = (1, 2); diff --git a/LanguageFeatures/Patterns/pattern_assignment_A05_t05.dart b/LanguageFeatures/Patterns/pattern_assignment_A05_t05.dart index 6f9b4d845c..c23ce70f98 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A05_t05.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A05_t05.dart @@ -69,7 +69,7 @@ main() { {"key1": af3, "key2": _} = {"key1": 1, "key2": 2}; Expect.equals(1, af3); - {"key1": af4, ...} = {"key1": 1, "key2": 2}; + {"key1": af4} = {"key1": 1, "key2": 2}; Expect.equals(1, af4); (af5, _) = (1, 2); diff --git a/LanguageFeatures/Patterns/pattern_assignment_A05_t06.dart b/LanguageFeatures/Patterns/pattern_assignment_A05_t06.dart index e430fd4164..6d0fa5bdf0 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A05_t06.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A05_t06.dart @@ -70,7 +70,7 @@ main() { }); Expect.throws(() { - {"key1": af4, ...} = {"key1": 1, "key2": 2}; + {"key1": af4} = {"key1": 1, "key2": 2}; }); Expect.throws(() { diff --git a/LanguageFeatures/Patterns/pattern_assignment_A06_t01.dart b/LanguageFeatures/Patterns/pattern_assignment_A06_t01.dart index 613d44a154..8b6915876f 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A06_t01.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A06_t01.dart @@ -60,7 +60,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": a, ...} = {"key1": 1, "key2": 2}; + {"key1": a} = {"key1": 1, "key2": 2}; // ^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A06_t02.dart b/LanguageFeatures/Patterns/pattern_assignment_A06_t02.dart index 52836c6410..ef67e9a1d7 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A06_t02.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A06_t02.dart @@ -61,7 +61,7 @@ class C { // [analyzer] unspecified // [cfe] unspecified - {"key1": a, ...} = {"key1": 1, "key2": 2}; + {"key1": a} = {"key1": 1, "key2": 2}; // ^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A06_t03.dart b/LanguageFeatures/Patterns/pattern_assignment_A06_t03.dart index c16aaaf585..e8887d3a53 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A06_t03.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A06_t03.dart @@ -63,7 +63,7 @@ class C extends A { // [analyzer] unspecified // [cfe] unspecified - {"key1": a, ...} = {"key1": 1, "key2": 2}; + {"key1": a} = {"key1": 1, "key2": 2}; // ^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A06_t04.dart b/LanguageFeatures/Patterns/pattern_assignment_A06_t04.dart index 0835624810..38d14a40db 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A06_t04.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A06_t04.dart @@ -63,7 +63,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": c.a, ...} = {"key1": 1, "key2": 2}; + {"key1": c.a} = {"key1": 1, "key2": 2}; // ^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A07_t01.dart b/LanguageFeatures/Patterns/pattern_assignment_A07_t01.dart index d7c919d77c..0e3c5ec9ca 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A07_t01.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A07_t01.dart @@ -57,7 +57,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": a, ...} = {"key1": "one", "key2": 2}; + {"key1": a} = {"key1": "one", "key2": 2}; // ^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/pattern_assignment_A08_t01.dart b/LanguageFeatures/Patterns/pattern_assignment_A08_t01.dart index a6f5acfefe..6708b3ec11 100644 --- a/LanguageFeatures/Patterns/pattern_assignment_A08_t01.dart +++ b/LanguageFeatures/Patterns/pattern_assignment_A08_t01.dart @@ -54,7 +54,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - {"key1": a, "key2": a, ...} = {"key1": "one", "key2": 2, "key3": 3}; + {"key1": a, "key2": a} = {"key1": "one", "key2": 2, "key3": 3}; // ^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/switch_statement_A01_t01.dart b/LanguageFeatures/Patterns/switch_statement_A01_t01.dart index 50393b2f07..48829bd7ad 100644 --- a/LanguageFeatures/Patterns/switch_statement_A01_t01.dart +++ b/LanguageFeatures/Patterns/switch_statement_A01_t01.dart @@ -115,10 +115,8 @@ String testMap(Map map) { return "map-1"; case {"key1": 1, "key2": _}: return "map-2"; - case {"key1": 1, "key2": 2, ...}: + case {"key1": 2, "key2": 2, "key3": 3}: return "map-3"; - case {"key1": 1, "key2": 2, "key3": 3}: - return "map-4"; default: return "default"; } @@ -175,7 +173,7 @@ main() { Expect.equals("list-3", testList([1, 2, 3])); Expect.equals("map-1", testMap({"key1": 1, "key2": 2})); Expect.equals("map-2", testMap({"key1": 1, "key2": 3})); - Expect.equals("map-3", testMap({"key1": 1, "key2": 2, "key3": 3})); + Expect.equals("map-3", testMap({"key1": 2, "key2": 2, "key3": 3})); Expect.equals("record-1", testRecord((1, 2))); Expect.equals("record-2", testRecord((1, 3))); Expect.equals("record-3", testRecord((1, 2, n: 3))); diff --git a/LanguageFeatures/Patterns/type_inference_A08_t01.dart b/LanguageFeatures/Patterns/type_inference_A08_t01.dart index 5b49e37d68..f4f521dadd 100644 --- a/LanguageFeatures/Patterns/type_inference_A08_t01.dart +++ b/LanguageFeatures/Patterns/type_inference_A08_t01.dart @@ -7,8 +7,7 @@ /// ... /// Map: A type schema Map where: /// i. If p has type arguments then K, and V are those type arguments. -/// ii. Else if p has no entries, then K and V are _. -/// iii. Else K is _ and V is the greatest lower bound of the context type +/// ii. Else K is _ and V is the greatest lower bound of the context type /// schemas of all value subpatterns. /// /// @description Check that if map pattern p has type arguments then K, and V @@ -46,10 +45,10 @@ main() { Expect.equals(typeOf>().toString(), log); log = ""; - var {} = getType({}, (String s) {log += s;}); + var {"k": _} = getType({"k": c}, (String s) {log += s;}); Expect.equals(typeOf>().toString(), log); log = ""; - final {} = getType({}, (String s) {log += s;}); + final {1: _} = getType({1: b}, (String s) {log += s;}); Expect.equals(typeOf>().toString(), log); } diff --git a/LanguageFeatures/Patterns/type_inference_A08_t02.dart b/LanguageFeatures/Patterns/type_inference_A08_t02.dart index 61af672f87..75f3f84fae 100644 --- a/LanguageFeatures/Patterns/type_inference_A08_t02.dart +++ b/LanguageFeatures/Patterns/type_inference_A08_t02.dart @@ -7,11 +7,12 @@ /// ... /// Map: A type schema Map where: /// i. If p has type arguments then K, and V are those type arguments. -/// ii. Else if p has no entries, then K and V are _. -/// iii. Else K is _ and V is the greatest lower bound of the context type +/// ii. Else K is _ and V is the greatest lower bound of the context type /// schemas of all value subpatterns. /// -/// @description Check that if map pattern p has no entries, then K and V are _. +/// @description Check that if map pattern p has no type arguments and do has +/// entries then K is _ and V is the greatest lower bound of the context type +/// schemas of all value subpatterns. /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=patterns,records @@ -19,12 +20,42 @@ import "../../Utils/expect.dart"; import "patterns_lib.dart"; +class A {} +class B extends A {} +class C extends B {} +class D extends C {} + main() { + A a = A(); + B b = B(); + C c = C(); + D d = D(); + String log = ""; - var {} = getType({}, (String s) {log += s;}); + try { + var {"key1": A v1, "key2": B v2, "key3": v3} = + getType({}, (String s) {log += s;}); + } catch (_) {} + Expect.equals(typeOf>().toString(), log); + + log = ""; + try { + final {"key1": A v1, "key2": B v2, "key3": v3} = + getType({}, (String s) {log += s;}); + } catch (_) {} + Expect.equals(typeOf>().toString(), log); + + log = ""; + try { + var {"key1": v1, "key2": v2, "key3": v3} = + getType({}, (String s) {log += s;}); + } catch (_) {} Expect.equals(typeOf>().toString(), log); log = ""; - final {} = getType({}, (String s) {log += s;}); + try { + final {"key1": v1, "key2": v2, "key3": v3} = + getType({}, (String s) {log += s;}); + } catch (_) {} Expect.equals(typeOf>().toString(), log); } diff --git a/LanguageFeatures/Patterns/type_inference_A08_t03.dart b/LanguageFeatures/Patterns/type_inference_A08_t03.dart deleted file mode 100644 index 4e6cc75e7f..0000000000 --- a/LanguageFeatures/Patterns/type_inference_A08_t03.dart +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// @assertion -/// The context type schema for a pattern p is: -/// ... -/// Map: A type schema Map where: -/// i. If p has type arguments then K, and V are those type arguments. -/// ii. Else if p has no entries, then K and V are _. -/// iii. Else K is _ and V is the greatest lower bound of the context type -/// schemas of all value subpatterns. -/// -/// @description Check that if map pattern p has no type arguments and do has -/// entries then K is _ and V is the greatest lower bound of the context type -/// schemas of all value subpatterns. -/// @author sgrekhov22@gmail.com - -// SharedOptions=--enable-experiment=patterns,records - -import "../../Utils/expect.dart"; -import "patterns_lib.dart"; - -class A {} -class B extends A {} -class C extends B {} -class D extends C {} - -main() { - A a = A(); - B b = B(); - C c = C(); - D d = D(); - - String log = ""; - try { - var {"key1": A v1, "key2": B v2, "key3": v3} = - getType({}, (String s) {log += s;}); - } catch (_) {} - Expect.equals(typeOf>().toString(), log); - - log = ""; - try { - final {"key1": A v1, "key2": B v2, "key3": v3} = - getType({}, (String s) {log += s;}); - } catch (_) {} - Expect.equals(typeOf>().toString(), log); - - log = ""; - try { - var {"key1": v1, "key2": v2, "key3": v3} = - getType({}, (String s) {log += s;}); - } catch (_) {} - Expect.equals(typeOf>().toString(), log); - - log = ""; - try { - final {"key1": v1, "key2": v2, "key3": v3, ...} = - getType({}, (String s) {log += s;}); - } catch (_) {} - Expect.equals(typeOf>().toString(), log); -} diff --git a/LanguageFeatures/Patterns/type_inference_A29_t01.dart b/LanguageFeatures/Patterns/type_inference_A29_t01.dart index 0a8c0326b7..2ca7258780 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t01.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t01.dart @@ -56,14 +56,14 @@ String test1() { String test2() { String ret = ""; switch ({const C(): 1}) { - case , num>{const C(): final a, ...}: + case , num>{const C(): final a}: a.expectStaticType>(); ret += "match;"; default: ret += "no match;"; } switch ({const C(): 1}) { - case , num>{const C(): final a, ...}: + case , num>{const C(): final a}: ret += "match;"; default: ret += "no match;"; @@ -90,13 +90,13 @@ String test3() { String test4() { String ret = ""; - if ({const C(): 1} case , num>{const C(): final a, ...}) { + if ({const C(): 1} case , num>{const C(): final a}) { a.expectStaticType>(); ret += "match;"; } else { ret += "no match;"; } - if ({const C(): 1} case , num>{const C(): final a, ...}) { + if ({const C(): 1} case , num>{const C(): final a}) { ret += "match;"; } else { ret += "no match;"; @@ -120,12 +120,12 @@ String test5() { String test6() { String ret = switch ({const C(): 1}) { - , num>{const C(): final a, ...} when + , num>{const C(): final a} when a.expectStaticType>() is num => "match;", _ => "no match;" }; ret += switch ({const C(): 1}) { - , num>{const C(): final a, ...} when + , num>{const C(): final a} when a.expectStaticType>() is num => "match;", _ => "no match;" }; @@ -133,10 +133,10 @@ String test6() { } main() { - var , num>{const C(): a1, ...} = {const C(): 1}; + var , num>{const C(): a1} = {const C(): 1}; a1.expectStaticType>(); a1 = 3.14; - final , num>{const C(): a2, ...} = {const C(): 1}; + final , num>{const C(): a2} = {const C(): 1}; a2.expectStaticType>(); Expect.equals("match;no match;", test1()); diff --git a/LanguageFeatures/Patterns/type_inference_A29_t03.dart b/LanguageFeatures/Patterns/type_inference_A29_t03.dart index cc3a6ff6a6..1bab9a68bd 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t03.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t03.dart @@ -40,7 +40,7 @@ String test1() { String test2() { switch ({"key1": 1 as num}) { - case {"key1": final a, ...}: + case {"key1": final a}: a.expectStaticType>(); return "match"; default: @@ -57,7 +57,7 @@ String test3() { } String test4() { - if ({"key1": 1 as num} case {"key1": final a, ...}) { + if ({"key1": 1 as num} case {"key1": final a}) { a.expectStaticType>(); return "match"; } @@ -73,7 +73,7 @@ String test5() => String test6() => switch ({"key1": 1 as num}) { - {"key1": final a, ...} when + {"key1": final a} when (a.expectStaticType>() is num)=> "match", _ => "no match" }; diff --git a/LanguageFeatures/Patterns/type_inference_A29_t04.dart b/LanguageFeatures/Patterns/type_inference_A29_t04.dart index 8ca1ec5398..1d14bbd5d8 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t04.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t04.dart @@ -38,7 +38,7 @@ String test1(dynamic d) { String test2(dynamic d) { switch (d) { - case {"key1": final String a, ...}: + case {"key1": final String a}: return "match"; default: return "no match"; @@ -53,7 +53,7 @@ String test3(dynamic d) { } String test4(dynamic d) { - if (d case {"key1": final String a, ...}) { + if (d case {"key1": final String a}) { return "match"; } return "no match"; @@ -67,7 +67,7 @@ String test5(dynamic d) => String test6(dynamic d) => switch (d) { - {"key1": final String a, ...} => "match", + {"key1": final String a} => "match", _ => "no match" }; diff --git a/LanguageFeatures/Patterns/type_inference_A29_t05.dart b/LanguageFeatures/Patterns/type_inference_A29_t05.dart index 6538d91c5f..a9ad36d6ca 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t05.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t05.dart @@ -31,7 +31,7 @@ main() { // ^^^^^^ // [analyzer] unspecified // [cfe] unspecified - final {"key1": final String a2, ...} = {} as dynamic; + final {"key1": final String a2} = {} as dynamic; // ^^^^^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/type_inference_A29_t06.dart b/LanguageFeatures/Patterns/type_inference_A29_t06.dart index b5a1b89f50..75d8ea4c78 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t06.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t06.dart @@ -51,7 +51,7 @@ String test1() { String test2() { switch (, int>{const D(): 1} as Object) { - case , num>{const D(): final a, ...}: + case , num>{const D(): final a}: a.expectStaticType>(); return "match"; default: @@ -71,7 +71,7 @@ String test3() { String test4() { if (, int>{const D(): 1} as Object - case , num>{const D(): final a, ...}) { + case , num>{const D(): final a}) { a.expectStaticType>(); return "match"; } @@ -87,7 +87,7 @@ String test5() => String test6() => switch (, int>{const D(): 1} as Object) { - , num>{const D(): final a, ...} when + , num>{const D(): final a} when a.expectStaticType>() is num => "match", _ => "no match" }; @@ -96,7 +96,7 @@ main() { var , num>{const D(): a1} = , int>{const D(): 1}; a1.expectStaticType>(); a1 = 3.14; - final , num>{const D(): a2, ...} = , int>{const D(): 1}; + final , num>{const D(): a2} = , int>{const D(): 1}; a2.expectStaticType>(); Expect.equals("match", test1()); diff --git a/LanguageFeatures/Patterns/type_inference_A29_t07.dart b/LanguageFeatures/Patterns/type_inference_A29_t07.dart index 1e9fd751aa..fba2dbfde3 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t07.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t07.dart @@ -43,7 +43,7 @@ String test1() { String test2() { switch (, int>{const C(): 1}) { - case {const C(): final a, ...}: + case {const C(): final a}: a.expectStaticType>(); return "match"; default: @@ -60,7 +60,7 @@ String test3() { } String test4() { - if (, int>{const C(): 1} case {const C(): final a, ...}) { + if (, int>{const C(): 1} case {const C(): final a}) { a.expectStaticType>(); return "match"; } @@ -75,7 +75,7 @@ String test5() => String test6() => switch (, int>{const C(): 1}) { - {const C(): final a, ...} when + {const C(): final a} when a.expectStaticType>() is int => "match", _ => "no match" }; @@ -84,7 +84,7 @@ main() { var {const C(): a1} = , int>{const C(): 1}; a1.expectStaticType>(); - final {const C(): a2, ...} = , int>{const C(): 1}; + final {const C(): a2} = , int>{const C(): 1}; a2.expectStaticType>(); var {1: a3, 2: b3} = {1: "str", 2: bool}; diff --git a/LanguageFeatures/Patterns/type_inference_A29_t08.dart b/LanguageFeatures/Patterns/type_inference_A29_t08.dart index 7bdfa27d1c..33299ce6ad 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t08.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t08.dart @@ -38,7 +38,7 @@ String test1() { String test2() { switch ({"key1": 1} as dynamic) { - case {"key1": final a, ...}: + case {"key1": final a}: Expect.throws(() {a.whatever;}); return "match"; default: @@ -56,7 +56,7 @@ String test3() { } String test4() { - if ({"key1": 1} as dynamic case {"key1": final a, ...}) { + if ({"key1": 1} as dynamic case {"key1": final a}) { Expect.throws(() {a.whatever;}); return "match"; } @@ -71,14 +71,14 @@ String test5() => String test6() => switch ({"key1": 1} as dynamic) { - {"key1": final a, ...} when a.whatever => "match", + {"key1": final a} when a.whatever => "match", _ => "no match" }; main() { var {"key1": a1} = {"key1": 1} as dynamic; Expect.throws(() {a1.whatever;}); - final {"key1": a2, ...} = {"key1": 1, "key2": 2} as dynamic; + final {"key1": a2} = {"key1": 1, "key2": 2} as dynamic; Expect.throws(() {a2.whatever;}); Expect.equals("match", test1()); diff --git a/LanguageFeatures/Patterns/type_inference_A29_t09.dart b/LanguageFeatures/Patterns/type_inference_A29_t09.dart index 0257fdef5a..7464bb34e7 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t09.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t09.dart @@ -41,7 +41,7 @@ String test1() { String test2() { switch ({"key1": 1 as num} as dynamic) { - case {"key1": final a, ...}: + case {"key1": final a}: Expect.throws(() { a.whatever; }); @@ -62,7 +62,7 @@ String test3() { } String test4() { - if ({"key1": 1 as num} as dynamic case {"key1": final a, ...}) { + if ({"key1": 1 as num} as dynamic case {"key1": final a}) { Expect.throws(() { a.whatever; }); @@ -79,7 +79,7 @@ String test5() => String test6() => switch ({"key1": 1 as num} as dynamic) { - {"key1": final a, ...} when a.whatever => "match", + {"key1": final a} when a.whatever => "match", _ => "no match" }; diff --git a/LanguageFeatures/Patterns/type_inference_A29_t10.dart b/LanguageFeatures/Patterns/type_inference_A29_t10.dart index 86acaa472f..0e1c57dfcc 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t10.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t10.dart @@ -32,7 +32,7 @@ main() { Expect.throws(() { a1.whatever; // a1 id dynamic }); - final {"key1": a2, ...} = {"key1": 1 as num, "key2": 2} as dynamic; + final {"key1": a2} = {"key1": 1 as num, "key2": 2} as dynamic; Expect.throws(() { a2.whatever; }); diff --git a/LanguageFeatures/Patterns/type_inference_A29_t11.dart b/LanguageFeatures/Patterns/type_inference_A29_t11.dart index d8ca398b38..6b05e9ca89 100644 --- a/LanguageFeatures/Patterns/type_inference_A29_t11.dart +++ b/LanguageFeatures/Patterns/type_inference_A29_t11.dart @@ -39,7 +39,7 @@ String test1() { String test2() { switch ({} as Object) { - case {"key1": final a, ...}: + case {"key1": final a}: a.expectStaticType>(); return "match"; default: @@ -56,7 +56,7 @@ String test3() { } String test4() { - if ({} as Object case {"key1": final a, ...}) { + if ({} as Object case {"key1": final a}) { a.expectStaticType>(); return "match"; } @@ -72,7 +72,7 @@ String test5() => String test6() => switch ({} as Object) { - {"key1": final a, ...} when + {"key1": final a} when (a.expectStaticType>() is Object?) => "match", _ => "no match" }; @@ -83,7 +83,7 @@ main() { a1.expectStaticType>(); }); Expect.throws(() { - final {"key1": a2, ...} = {}; + final {"key1": a2} = {}; }); Expect.equals("no match", test1()); Expect.equals("no match", test2()); diff --git a/LanguageFeatures/Patterns/variable_declaration_A01_t01.dart b/LanguageFeatures/Patterns/variable_declaration_A01_t01.dart index 8027ed7e4f..901f221d70 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A01_t01.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A01_t01.dart @@ -54,7 +54,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - Map {"pi": a4, ...} = {"pi": 3.14, "e": 2.71}; + Map {"pi": a4} = {"pi": 3.14, "e": 2.71}; // ^^^^^^^^^^^^^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/variable_declaration_A01_t02.dart b/LanguageFeatures/Patterns/variable_declaration_A01_t02.dart index cb686f7710..bb99252195 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A01_t02.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A01_t02.dart @@ -54,8 +54,8 @@ main() { // [analyzer] unspecified // [cfe] unspecified - const {"pi": a4, ...} = {"pi": 3.14, "e": 2.71}; -// ^^^^^^^^^^^^^^^ + const {"pi": a4} = {"pi": 3.14, "e": 2.71}; +// ^^^^^^^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/variable_declaration_A01_t03.dart b/LanguageFeatures/Patterns/variable_declaration_A01_t03.dart index ecd0dc9c6d..1d29a8f115 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A01_t03.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A01_t03.dart @@ -44,8 +44,8 @@ main() { // [analyzer] unspecified // [cfe] unspecified - var {"pi": a4, ...} = {"pi": 3.14, "e": 2.71}, (n2, s2) = (1, "str"); -// ^ + var {"pi": a4} = {"pi": 3.14, "e": 2.71}, (n2, s2) = (1, "str"); +// ^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/variable_declaration_A01_t04.dart b/LanguageFeatures/Patterns/variable_declaration_A01_t04.dart index a3b72b3381..8b8989ab21 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A01_t04.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A01_t04.dart @@ -44,8 +44,8 @@ main() { // [analyzer] unspecified // [cfe] unspecified - var {"pi": a3, ...} = {"pi": 3.14, "e": 2.71}, c3 = 42; -// ^ + var {"pi": a3} = {"pi": 3.14, "e": 2.71}, c3 = 42; +// ^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/variable_declaration_A01_t05.dart b/LanguageFeatures/Patterns/variable_declaration_A01_t05.dart index b08b9456d2..4bb9821724 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A01_t05.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A01_t05.dart @@ -54,8 +54,8 @@ main() { // [analyzer] unspecified // [cfe] unspecified - final {"pi": a4, ...}; -// ^^^^^^^^^^^^^^^ + final {"pi": a4}; +// ^^^^^^^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/variable_declaration_A01_t06.dart b/LanguageFeatures/Patterns/variable_declaration_A01_t06.dart index 3bf0c3dd10..3e8c9affca 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A01_t06.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A01_t06.dart @@ -54,8 +54,8 @@ main() { // [analyzer] unspecified // [cfe] unspecified - final {"pi": a4, ...}, x4 = 42; -// ^^^^^^^^^^^^^^^ + final {"pi": a4}, x4 = 42; +// ^^^^^^^^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Patterns/variable_declaration_A03_t05.dart b/LanguageFeatures/Patterns/variable_declaration_A03_t05.dart index 22c16eca37..e93bf68a33 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A03_t05.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A03_t05.dart @@ -34,7 +34,7 @@ main() { a2 = 42; b2 = 42; - var {"key1": int a3, "key2": b3, ...} + var {"key1": int a3, "key2": b3} = {"key1": 5, "key2": 6, "key3": 7}; Expect.equals(5, a3); Expect.equals(6, b3); @@ -49,7 +49,7 @@ main() { Expect.equals(3, a5); Expect.equals(4, b5); - final {"key1": int a6, "key2": b6, ...} + final {"key1": int a6, "key2": b6} = {"key1": 5, "key2": 6, "key3": 7}; Expect.equals(5, a6); Expect.equals(6, b6); diff --git a/LanguageFeatures/Patterns/variable_declaration_A03_t06.dart b/LanguageFeatures/Patterns/variable_declaration_A03_t06.dart index 8270162eac..d2d9e9233a 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A03_t06.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A03_t06.dart @@ -33,7 +33,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - final {"key1": int a2, "key2": b2, ...} = {"key1": 1, "key2": 2, "key3": 3}; + final {"key1": int a2, "key2": b2} = {"key1": 1, "key2": 2, "key3": 3}; a2 = 42; //^^ // [analyzer] unspecified @@ -43,7 +43,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified - final {"key1": a3, "key2": int b3, ...} + final {"key1": a3, "key2": int b3} = {"key1": 1, "key2": 2, "key3": 3}; a3 = 42; //^^ diff --git a/LanguageFeatures/Patterns/variable_declaration_A04_t05.dart b/LanguageFeatures/Patterns/variable_declaration_A04_t05.dart index 0a2ca46f54..36f9dfd10a 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A04_t05.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A04_t05.dart @@ -47,7 +47,7 @@ main() { Expect.isTrue(visited); visited = false; - for (var {"key1": int a3, "key2": b3, ...} + for (var {"key1": int a3, "key2": b3} in [{"key1": 5, "key2": 6, "key3": 7}]) { Expect.equals(5, a3); Expect.equals(6, b3); @@ -73,7 +73,7 @@ main() { Expect.isTrue(visited); visited = false; - for(final {"key1": int a6, "key2": b6, ...} + for(final {"key1": int a6, "key2": b6} in [{"key1": 5, "key2": 6, "key3": 7}]) { Expect.equals(5, a6); Expect.equals(6, b6); diff --git a/LanguageFeatures/Patterns/variable_declaration_A04_t06.dart b/LanguageFeatures/Patterns/variable_declaration_A04_t06.dart index 5cecb033d7..0e4b791999 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A04_t06.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A04_t06.dart @@ -36,7 +36,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified } - for (final {"key1": int a2, "key2": b2, ...} + for (final {"key1": int a2, "key2": b2} in [{"key1": 1, "key2": 2, "key3": 3}]) { a2 = 42; // ^^ @@ -47,7 +47,7 @@ main() { // [analyzer] unspecified // [cfe] unspecified } - for (final {"key1": a3, "key2": int b3, ...} + for (final {"key1": a3, "key2": int b3} in [{"key1": 1, "key2": 2, "key3": 3}]) { a3 = 42; // ^^ From 26f8fab0d6f7bfd3d3b6c8f79a8fe9df7a9e9686 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Fri, 31 Mar 2023 12:47:43 +0300 Subject: [PATCH 4/7] Some analyzer failures fixed --- LanguageFeatures/Patterns/switch_expression_A01_t02.dart | 9 ++++++--- LanguageFeatures/Patterns/switch_expression_A01_t03.dart | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/LanguageFeatures/Patterns/switch_expression_A01_t02.dart b/LanguageFeatures/Patterns/switch_expression_A01_t02.dart index 61dc03036c..b10d5f592f 100644 --- a/LanguageFeatures/Patterns/switch_expression_A01_t02.dart +++ b/LanguageFeatures/Patterns/switch_expression_A01_t02.dart @@ -32,6 +32,9 @@ main () { int i = 42; var x = switch(i) { +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified 1: "one" // ^ // [analyzer] unspecified @@ -48,13 +51,13 @@ main () { }; var z = switch(i) { - 1: "one", -// ^ +// ^^^^^^ // [analyzer] unspecified // [cfe] unspecified - _: "zero" + 1: "one", // ^ // [analyzer] unspecified // [cfe] unspecified + _: "zero" }; } diff --git a/LanguageFeatures/Patterns/switch_expression_A01_t03.dart b/LanguageFeatures/Patterns/switch_expression_A01_t03.dart index 6f188f225f..63303213a1 100644 --- a/LanguageFeatures/Patterns/switch_expression_A01_t03.dart +++ b/LanguageFeatures/Patterns/switch_expression_A01_t03.dart @@ -33,13 +33,13 @@ main () { int i = 42; var x = switch(i) { 1 => "one" -// ^ -// [analyzer] unspecified -// [cfe] unspecified 2 => "two" // ^ // [analyzer] unspecified // [cfe] unspecified _ => "any" +// ^ +// [analyzer] unspecified +// [cfe] unspecified }; } From 6d493890c24680b208e99c5424dc7f45bd201043 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Fri, 31 Mar 2023 13:07:04 +0200 Subject: [PATCH 5/7] Update variable_declaration_A01_t01.dart --- LanguageFeatures/Patterns/variable_declaration_A01_t01.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LanguageFeatures/Patterns/variable_declaration_A01_t01.dart b/LanguageFeatures/Patterns/variable_declaration_A01_t01.dart index 901f221d70..e1c9b0835d 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A01_t01.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A01_t01.dart @@ -55,7 +55,7 @@ main() { // [cfe] unspecified Map {"pi": a4} = {"pi": 3.14, "e": 2.71}; -// ^^^^^^^^^^^^^^^ +// ^^^^^^^^^^ // [analyzer] unspecified // [cfe] unspecified From 8ff1c4a8a73ae35be61acca8224550f3e9b883ad Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Fri, 31 Mar 2023 13:07:50 +0200 Subject: [PATCH 6/7] Update variable_declaration_A01_t05.dart --- LanguageFeatures/Patterns/variable_declaration_A01_t05.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LanguageFeatures/Patterns/variable_declaration_A01_t05.dart b/LanguageFeatures/Patterns/variable_declaration_A01_t05.dart index 4bb9821724..8294af53c0 100644 --- a/LanguageFeatures/Patterns/variable_declaration_A01_t05.dart +++ b/LanguageFeatures/Patterns/variable_declaration_A01_t05.dart @@ -55,7 +55,7 @@ main() { // [cfe] unspecified final {"pi": a4}; -// ^^^^^^^^^ +// ^^^^^^^^^^ // [analyzer] unspecified // [cfe] unspecified From e6b5e69d2632c3696a5ba20da018065fdf37ff26 Mon Sep 17 00:00:00 2001 From: "Sergey G. Grekhov" Date: Fri, 31 Mar 2023 17:52:44 +0300 Subject: [PATCH 7/7] #1976. Runtime errors fixed --- LanguageFeatures/Patterns/if_case_A02_t01.dart | 2 +- LanguageFeatures/Patterns/if_case_A02_t02.dart | 2 +- LanguageFeatures/Patterns/if_case_A02_t03.dart | 2 +- LanguageFeatures/Patterns/map_A01_t04.dart | 2 +- LanguageFeatures/Patterns/map_A04_t02.dart | 6 +++--- .../Patterns/pattern_context_A07_t01.dart | 8 ++++---- .../Patterns/pattern_context_A07_t02.dart | 8 ++++---- .../Patterns/pattern_context_A07_t03.dart | 8 ++++---- .../Patterns/variable_A02_t01.dart | 6 +++--- .../Patterns/wildcards_A01_t02.dart | 18 +++++++++--------- 10 files changed, 31 insertions(+), 31 deletions(-) diff --git a/LanguageFeatures/Patterns/if_case_A02_t01.dart b/LanguageFeatures/Patterns/if_case_A02_t01.dart index b6df7d3638..1b8f3007be 100644 --- a/LanguageFeatures/Patterns/if_case_A02_t01.dart +++ b/LanguageFeatures/Patterns/if_case_A02_t01.dart @@ -175,7 +175,7 @@ main() { Expect.listEquals([1, 2, 4], testMap1({"key1": 1, "key2": 2})); Expect.listEquals([1, 3, 4], testMap1({"key1": 2, "key2": 2})); Expect.listEquals([1, 3, 4], testMap1({"key1": 1, "key2": -2})); - Expect.listEquals([1, 3, 4], testMap1({"key1": 1, "key2": 2, "key3": 3})); + Expect.listEquals([1, 2, 4], testMap1({"key1": 1, "key2": 2, "key3": 3})); Expect.listEquals([1, 2, 4], testMap2({"key1": 1, "key2": -2})); Expect.listEquals([1, 3, 4], testMap2({"key1": 2, "key2": -2})); Expect.listEquals([1, 3, 4], testMap2({"key1": 1, "key2": 2})); diff --git a/LanguageFeatures/Patterns/if_case_A02_t02.dart b/LanguageFeatures/Patterns/if_case_A02_t02.dart index eda9efddcf..3da5ca27f8 100644 --- a/LanguageFeatures/Patterns/if_case_A02_t02.dart +++ b/LanguageFeatures/Patterns/if_case_A02_t02.dart @@ -274,7 +274,7 @@ main() { testMap1({"key1": 2, "key2": 2})); Expect.mapEquals({"key1": 1, "key3": 3, "key4": 4}, testMap1({"key1": 1, "key2": -2})); - Expect.mapEquals({"key1": 1, "key3": 3, "key4": 4}, + Expect.mapEquals({"key1": 1, "key2": 2, "key4": 4}, testMap1({"key1": 1, "key2": 2, "key3": 3})); Expect.mapEquals({"key1": 1, "key2": 2, "key4": 4}, testMap2({"key1": 1, "key2": -2})); diff --git a/LanguageFeatures/Patterns/if_case_A02_t03.dart b/LanguageFeatures/Patterns/if_case_A02_t03.dart index d054cbe708..d24a6be7d2 100644 --- a/LanguageFeatures/Patterns/if_case_A02_t03.dart +++ b/LanguageFeatures/Patterns/if_case_A02_t03.dart @@ -249,7 +249,7 @@ main() { Expect.setEquals({1, 2, 4}, testMap1({"key1": 1, "key2": 2})); Expect.setEquals({1, 3, 4}, testMap1({"key1": 2, "key2": 2})); Expect.setEquals({1, 3, 4}, testMap1({"key1": 1, "key2": -2})); - Expect.setEquals({1, 3, 4}, testMap1({"key1": 1, "key2": 2, "key3": 3})); + Expect.setEquals({1, 2, 4}, testMap1({"key1": 1, "key2": 2, "key3": 3})); Expect.setEquals({1, 2, 4}, testMap2({"key1": 1, "key2": -2})); Expect.setEquals({1, 3, 4}, testMap2({"key1": 2, "key2": -2})); Expect.setEquals({1, 3, 4}, testMap2({"key1": 1, "key2": 2})); diff --git a/LanguageFeatures/Patterns/map_A01_t04.dart b/LanguageFeatures/Patterns/map_A01_t04.dart index 92079d2129..5667fbe2cf 100644 --- a/LanguageFeatures/Patterns/map_A01_t04.dart +++ b/LanguageFeatures/Patterns/map_A01_t04.dart @@ -54,6 +54,6 @@ main() { final {1: a, 2: b!} = {1: 1, 2: null}; }); Expect.throws(() { - var {1: a, 2: b} = {1: "1", 2: "2", 3: "3"}; + var {1: a, 2: b} = {1: "1", 3: "3"}; }); } diff --git a/LanguageFeatures/Patterns/map_A04_t02.dart b/LanguageFeatures/Patterns/map_A04_t02.dart index ac8c25f6b4..57df7f5847 100644 --- a/LanguageFeatures/Patterns/map_A04_t02.dart +++ b/LanguageFeatures/Patterns/map_A04_t02.dart @@ -83,11 +83,11 @@ main() { Expect.equals("a=1, b=2", test1({c1: 1, c2: 2})); Expect.equals("default", test1({c1: 1})); - Expect.equals("default", test1({c1: 1, c2: 2, c3: 3})); + Expect.equals("a=1, b=2", test1({c1: 1, c2: 2, c3: 3})); Expect.equals("a=1, b=2", test2({c1: 1, c2: 2})); Expect.equals("default", test2({c1: 1})); - Expect.equals("default", test2({c1: 1, c2: 2, c3: 3})); + Expect.equals("a=1, b=2", test2({c1: 1, c2: 2, c3: 3})); Expect.equals("a=1, b=2", test3({c1: 1, c2: 2})); Expect.equals("default", test3({c1: 1})); - Expect.equals("default", test3({c1: 1, c2: 2, c3: 3})); + Expect.equals("a=1, b=2", test3({c1: 1, c2: 2, c3: 3})); } diff --git a/LanguageFeatures/Patterns/pattern_context_A07_t01.dart b/LanguageFeatures/Patterns/pattern_context_A07_t01.dart index a031e0291c..a893acc2d0 100644 --- a/LanguageFeatures/Patterns/pattern_context_A07_t01.dart +++ b/LanguageFeatures/Patterns/pattern_context_A07_t01.dart @@ -465,10 +465,10 @@ main() { Expect.equals("match", testMap2({"key1": 1})); Expect.equals("match", testMap3({"key1": 1})); Expect.equals("match", testMap4({"key1": 1})); - Expect.equals("no match", testMap1({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap2({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap3({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap4({"key1": 1, "key2": 2})); + Expect.equals("match", testMap1({"key1": 1, "key2": 2})); + Expect.equals("match", testMap2({"key1": 1, "key2": 2})); + Expect.equals("match", testMap3({"key1": 1, "key2": 2})); + Expect.equals("match", testMap4({"key1": 1, "key2": 2})); Expect.equals("match", testRecord1((1,))); Expect.equals("match", testRecord2((1,))); Expect.equals("match", testRecord3((1,))); diff --git a/LanguageFeatures/Patterns/pattern_context_A07_t02.dart b/LanguageFeatures/Patterns/pattern_context_A07_t02.dart index 793e7fd504..7878aae615 100644 --- a/LanguageFeatures/Patterns/pattern_context_A07_t02.dart +++ b/LanguageFeatures/Patterns/pattern_context_A07_t02.dart @@ -333,10 +333,10 @@ main() { Expect.equals("match", testMap2({"key1": 1})); Expect.equals("match", testMap3({"key1": 1})); Expect.equals("match", testMap4({"key1": 1})); - Expect.equals("no match", testMap1({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap2({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap3({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap4({"key1": 1, "key2": 2})); + Expect.equals("match", testMap1({"key1": 1, "key2": 2})); + Expect.equals("match", testMap2({"key1": 1, "key2": 2})); + Expect.equals("match", testMap3({"key1": 1, "key2": 2})); + Expect.equals("match", testMap4({"key1": 1, "key2": 2})); Expect.equals("match", testRecord1((1,))); Expect.equals("match", testRecord2((1,))); Expect.equals("match", testRecord3((1,))); diff --git a/LanguageFeatures/Patterns/pattern_context_A07_t03.dart b/LanguageFeatures/Patterns/pattern_context_A07_t03.dart index 9cc1ac3ca9..38dfaa56c4 100644 --- a/LanguageFeatures/Patterns/pattern_context_A07_t03.dart +++ b/LanguageFeatures/Patterns/pattern_context_A07_t03.dart @@ -377,10 +377,10 @@ main() { Expect.equals("match", testMap2({"key1": 1})); Expect.equals("match", testMap3({"key1": 1})); Expect.equals("match", testMap4({"key1": 1})); - Expect.equals("no match", testMap1({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap2({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap3({"key1": 1, "key2": 2})); - Expect.equals("no match", testMap4({"key1": 1, "key2": 2})); + Expect.equals("match", testMap1({"key1": 1, "key2": 2})); + Expect.equals("match", testMap2({"key1": 1, "key2": 2})); + Expect.equals("match", testMap3({"key1": 1, "key2": 2})); + Expect.equals("match", testMap4({"key1": 1, "key2": 2})); Expect.equals("match", testRecord1((1,))); Expect.equals("match", testRecord2((1,))); Expect.equals("match", testRecord3((1,))); diff --git a/LanguageFeatures/Patterns/variable_A02_t01.dart b/LanguageFeatures/Patterns/variable_A02_t01.dart index 635336a212..639e4c4a4b 100644 --- a/LanguageFeatures/Patterns/variable_A02_t01.dart +++ b/LanguageFeatures/Patterns/variable_A02_t01.dart @@ -209,20 +209,20 @@ main() { Expect.equals("default", testList3(["x"])); Expect.equals("{1: 2}", testMap1({1: 2})); - Expect.equals("default", testMap1({1: 3, 3: 4})); + Expect.equals("{1: 3}", testMap1({1: 3, 3: 4})); Expect.equals("{2: x}", testMap1({2: "x"})); Expect.equals("default", testMap1({3: 3})); Expect.equals("default", testMap1({})); Expect.equals("{1: 2}", testMap2({1: 2})); - Expect.equals("default", testMap2({1: 3, 3: 4})); + Expect.equals("{1: 3}", testMap2({1: 3, 3: 4})); Expect.equals("{2: x}", testMap2({2: "x"})); Expect.equals("{2: true}", testMap2({2: true})); Expect.equals("default", testMap2({3: 3})); Expect.equals("default", testMap2({})); Expect.equals("{1: 2}", testMap3({1: 2})); - Expect.equals("default", testMap3({1: 3, 3: 4})); + Expect.equals("{1: 3}", testMap3({1: 3, 3: 4})); Expect.equals("{2: x}", testMap3({2: "x"})); Expect.equals("default", testMap3({3: 3})); Expect.equals("default", testMap3({})); diff --git a/LanguageFeatures/Patterns/wildcards_A01_t02.dart b/LanguageFeatures/Patterns/wildcards_A01_t02.dart index ac27ba06ce..f1569a683c 100644 --- a/LanguageFeatures/Patterns/wildcards_A01_t02.dart +++ b/LanguageFeatures/Patterns/wildcards_A01_t02.dart @@ -74,31 +74,31 @@ main() { Expect.equals("{1: _}", test1({1: 2})); Expect.equals("{1: _}", test1({1: 3})); Expect.equals("{42: String _}", test1({42: ""})); - Expect.equals("default", test1({42: "", 2: "2"})); + Expect.equals("{42: String _}", test1({42: "", 2: "2"})); Expect.equals("default", test1({2: 1})); Expect.equals("default", test1({3: 2, 2: 1})); Expect.equals("default", test1({})); - Expect.equals("default", test1({1: 2, 2: 1})); - Expect.equals("default", test1({1: 3, 42: ""})); + Expect.equals("{1: _}", test1({1: 2, 2: 1})); + Expect.equals("{1: _}", test1({1: 3, 42: ""})); Expect.equals("{1: _}", test2({1: 2})); Expect.equals("{1: _}", test2({1: 3})); Expect.equals("{42: String _}", test2({42: ""})); - Expect.equals("default", test2({42: "", 2: "2"})); + Expect.equals("{42: String _}", test2({42: "", 2: "2"})); Expect.equals("default", test2({2: 1})); Expect.equals("default", test2({3: 2, 2: 1})); Expect.equals("default", test2({})); - Expect.equals("default", test2({1: 2, 2: 1})); - Expect.equals("default", test2({1: 3, 42: ""})); + Expect.equals("{1: _}", test2({1: 2, 2: 1})); + Expect.equals("{1: _}", test2({1: 3, 42: ""})); Expect.equals("{1: _}", test3({1: 2})); Expect.equals("{1: _}", test3({1: 3})); Expect.equals("{42: String _}", test3({42: ""})); - Expect.equals("default", test3({42: "", 2: "2"})); + Expect.equals("{42: String _}", test3({42: "", 2: "2"})); Expect.equals("default", test3({2: 1})); Expect.equals("default", test3({3: 2, 2: 1})); Expect.equals("default", test3({})); - Expect.equals("default", test3({1: 2, 2: 1})); - Expect.equals("default", test3({1: 3, 42: ""})); + Expect.equals("{1: _}", test3({1: 2, 2: 1})); + Expect.equals("{1: _}", test3({1: 3, 42: ""})); }