Skip to content

Commit e6d352d

Browse files
johnniwintherCommit Queue
authored and
Commit Queue
committed
[_fe_analyzer_shared] Update exhaustiveness checking to new semantics
In response to dart-lang/language#2960 Change-Id: I26430aa7666de69b9bbc34ded65e0e54160e3d3c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/292004 Reviewed-by: Paul Berry <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 6424b82 commit e6d352d

File tree

6 files changed

+78
-85
lines changed

6 files changed

+78
-85
lines changed

pkg/_fe_analyzer_shared/lib/src/exhaustiveness/shared.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,6 @@ mixin SpaceCreator<Pattern extends Object, Type extends Object> {
623623
required Type keyType,
624624
required Type valueType,
625625
required Map<MapKey, Pattern> entries,
626-
required bool hasRest,
627626
required bool hasExplicitTypeArguments}) {
628627
String typeArgumentsText;
629628
if (hasExplicitTypeArguments) {
@@ -639,8 +638,7 @@ mixin SpaceCreator<Pattern extends Object, Type extends Object> {
639638
}
640639

641640
MapTypeRestriction<Type> identity = new MapTypeRestriction(
642-
keyType, valueType, entries.keys.toSet(), typeArgumentsText,
643-
hasRest: hasRest);
641+
keyType, valueType, entries.keys.toSet(), typeArgumentsText);
644642
StaticType staticType = createMapType(type, identity);
645643

646644
Map<Key, Space> additionalFields = {};

pkg/_fe_analyzer_shared/lib/src/exhaustiveness/types/map.dart

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ class MapPatternStaticType<Type extends Object>
2424
buffer.write('$key: $space');
2525
first = false;
2626
});
27-
if (restriction.hasRest) {
28-
if (!first) buffer.write(', ');
29-
buffer.write('...');
30-
}
3127

3228
buffer.write('}');
3329
return buffer.toString();
@@ -50,10 +46,6 @@ class MapPatternStaticType<Type extends Object>
5046
}
5147
comma = ', ';
5248
}
53-
if (restriction.hasRest) {
54-
buffer.write(comma);
55-
buffer.write('...');
56-
}
5749
buffer.write('}');
5850

5951
// If we have restrictions on the record type we create an and pattern.
@@ -91,30 +83,26 @@ class MapTypeRestriction<Type extends Object> implements Restriction<Type> {
9183
final Type keyType;
9284
final Type valueType;
9385
final Set<MapKey> keys;
94-
final bool hasRest;
9586
final String typeArgumentsText;
9687

9788
MapTypeRestriction(
98-
this.keyType, this.valueType, this.keys, this.typeArgumentsText,
99-
{required this.hasRest});
89+
this.keyType, this.valueType, this.keys, this.typeArgumentsText);
10090

10191
@override
10292
late final int hashCode =
103-
Object.hash(keyType, valueType, Object.hashAllUnordered(keys), hasRest);
93+
Object.hash(keyType, valueType, Object.hashAllUnordered(keys));
10494

10595
@override
10696
bool get isUnrestricted {
10797
// The map pattern containing only a rest pattern covers the whole type.
108-
return hasRest && keys.isEmpty;
98+
return keys.isEmpty;
10999
}
110100

111101
@override
112102
bool operator ==(Object other) {
113103
if (identical(this, other)) return true;
114104
if (other is! MapTypeRestriction<Type>) return false;
115-
if (keyType != other.keyType ||
116-
valueType != other.valueType ||
117-
hasRest != other.hasRest) {
105+
if (keyType != other.keyType || valueType != other.valueType) {
118106
return false;
119107
}
120108
if (keys.length != other.keys.length) return false;
@@ -127,13 +115,7 @@ class MapTypeRestriction<Type extends Object> implements Restriction<Type> {
127115
if (other is! MapTypeRestriction<Type>) return false;
128116
if (!typeOperations.isSubtypeOf(keyType, other.keyType)) return false;
129117
if (!typeOperations.isSubtypeOf(valueType, other.valueType)) return false;
130-
if (other.hasRest) {
131-
return keys.containsAll(other.keys);
132-
} else if (hasRest) {
133-
return false;
134-
} else {
135-
return keys.length == other.keys.length && keys.containsAll(other.keys);
136-
}
118+
return keys.containsAll(other.keys);
137119
}
138120

139121
@override
@@ -148,11 +130,6 @@ class MapTypeRestriction<Type extends Object> implements Restriction<Type> {
148130
sb.write(': ()');
149131
comma = ', ';
150132
}
151-
if (hasRest) {
152-
sb.write(comma);
153-
sb.write('...');
154-
comma = ', ';
155-
}
156133
sb.write('}');
157134
return sb.toString();
158135
}

pkg/_fe_analyzer_shared/test/exhaustiveness/data/map.dart

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
untypedMap(Map map) {
6-
var a = /*type=Map<dynamic, dynamic>*/ switch (map) {
7-
{} /*space={}*/ => 0,
8-
{1: _} /*space={1: ()}*/ => 1,
6+
var a = /*
7+
fields={isEmpty:bool},
8+
type=Map<dynamic, dynamic>
9+
*/
10+
switch (map) {
11+
Map(isEmpty: true) /*space=Map<dynamic, dynamic>(isEmpty: true)*/ => 0,
12+
{1: _, 2: _, 3: _} /*space={1: (), 2: (), 3: ()}*/ => 3,
913
{1: _, 2: _} /*space={1: (), 2: ()}*/ => 2,
10-
Map() /*space={...}*/ => 3,
14+
{1: _} /*space={1: ()}*/ => 1,
15+
Map() /*space=Map<dynamic, dynamic>*/ => 4,
1116
};
1217
var b = /*type=Map<dynamic, dynamic>*/ switch (map) {
13-
Map() /*space={...}*/ => 0,
18+
Map() /*space=Map<dynamic, dynamic>*/ => 0,
1419
};
1520
}
1621

@@ -22,30 +27,36 @@ class C extends A {}
2227

2328
typedMap(Map<int, A> map) {
2429
var a = /*
25-
error=non-exhaustive:Map<int, A>(),
30+
error=non-exhaustive:Map<int, A>(isEmpty: false),
31+
fields={isEmpty:bool},
2632
type=Map<int, A>
2733
*/
2834
switch (map) {
29-
{} /*space={}*/ => 0,
35+
Map(isEmpty: true) /*space=Map<int, A>(isEmpty: true)*/ => 0,
36+
{0: B b, 1: _} /*space={0: B, 1: A}*/ => 4,
37+
{0: C c, 1: _} /*space={0: C, 1: A}*/ => 5,
38+
{0: _, 1: _} /*
39+
error=unreachable,
40+
space={0: A, 1: A}
41+
*/
42+
=>
43+
3,
3044
{0: B b} /*space={0: B}*/ => 1,
3145
{0: C c} /*space={0: C}*/ => 2,
32-
{0: _, 1: _} /*space={0: A, 1: A}*/ => 3,
33-
{0: B b} /*space={0: B, ...}*/ => 4,
34-
{0: C c} /*space={0: C, ...}*/ => 5,
3546
};
3647

3748
var b = /*type=Map<int, A>*/ switch (map) {
38-
{...} /*space={...}*/ => 0,
49+
Map() /*space=Map<int, A>*/ => 0,
3950
};
4051
var c = /*
4152
error=non-exhaustive:Map<int, A>(),
4253
type=Map<int, A>
4354
*/
4455
switch (map) {
45-
Map<int, B>() /*space=<int, B>{...}*/ => 0,
56+
Map<int, B>() /*space=Map<int, B>*/ => 0,
4657
};
4758
var d = /*type=Map<int, B>*/ switch (map) {
48-
Map() /*space={...}*/ => 0,
59+
Map() /*space=Map<int, B>*/ => 0,
4960
{1: _} /*
5061
error=unreachable,
5162
space={1: B}
@@ -54,7 +65,7 @@ typedMap(Map<int, A> map) {
5465
1,
5566
{2: _} /*
5667
error=unreachable,
57-
space={2: B, ...}
68+
space={2: B}
5869
*/
5970
=>
6071
2,
@@ -63,13 +74,13 @@ typedMap(Map<int, A> map) {
6374

6475
exhaustiveRestOnly(Map o) {
6576
return /*type=Map<dynamic, dynamic>*/ switch (o) {
66-
Map() /*space={...}*/ => 0,
77+
Map() /*space=Map<dynamic, dynamic>*/ => 0,
6778
};
6879
}
6980

7081
unreachableAfterRestOnly(Map o) {
7182
return /*type=Map<dynamic, dynamic>*/ switch (o) {
72-
Map() /*space={...}*/ => 0,
83+
Map() /*space=Map<dynamic, dynamic>*/ => 0,
7384
{0: _} /*
7485
error=unreachable,
7586
space={0: ()}
@@ -81,7 +92,7 @@ unreachableAfterRestOnly(Map o) {
8192

8293
unreachableAfterRestOnlyTyped(Map o) {
8394
return /*type=Map<dynamic, dynamic>*/ switch (o) {
84-
Map() /*space={...}*/ => 0,
95+
Map() /*space=Map<dynamic, dynamic>*/ => 0,
8596
<int, String>{
8697
0: _
8798
} /*
@@ -94,11 +105,17 @@ unreachableAfterRestOnlyTyped(Map o) {
94105
}
95106

96107
unreachableAfterRestOnlyEmpty(Map o) {
97-
return /*type=Map<dynamic, dynamic>*/ switch (o) {
98-
Map() /*space={...}*/ => 0,
99-
{} /*
108+
return /*
109+
fields={isEmpty:bool},
110+
type=Map<dynamic, dynamic>
111+
*/
112+
switch (o) {
113+
Map() /*space=Map<dynamic, dynamic>*/ => 0,
114+
Map(
115+
isEmpty: true
116+
) /*
100117
error=unreachable,
101-
space={}
118+
space=Map<dynamic, dynamic>(isEmpty: true)
102119
*/
103120
=>
104121
1,
@@ -107,14 +124,14 @@ unreachableAfterRestOnlyEmpty(Map o) {
107124

108125
unreachableAfterRestSameKeys(Map o) {
109126
return /*type=Map<dynamic, dynamic>*/ switch (o) {
110-
{0: _} /*space={0: (), ...}*/ => 0,
127+
{0: _} /*space={0: ()}*/ => 0,
111128
{0: _} /*
112129
error=unreachable,
113130
space={0: ()}
114131
*/
115132
=>
116133
1,
117-
Map() /*space={...}*/ => 2,
134+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
118135
};
119136
}
120137

@@ -124,7 +141,7 @@ nonExhaustiveAfterRestSameKeys(Map o) {
124141
type=Map<dynamic, dynamic>
125142
*/
126143
switch (o) {
127-
{0: _} /*space={0: (), ...}*/ => 0,
144+
{0: _} /*space={0: ()}*/ => 0,
128145
{0: _} /*
129146
error=unreachable,
130147
space={0: ()}
@@ -136,7 +153,7 @@ nonExhaustiveAfterRestSameKeys(Map o) {
136153

137154
unreachableAfterRestMoreKeys(Map o) {
138155
return /*type=Map<dynamic, dynamic>*/ switch (o) {
139-
{0: _} /*space={0: (), ...}*/ => 0,
156+
{0: _} /*space={0: ()}*/ => 0,
140157
{
141158
0: _,
142159
1: _
@@ -146,7 +163,7 @@ unreachableAfterRestMoreKeys(Map o) {
146163
*/
147164
=>
148165
1,
149-
Map() /*space={...}*/ => 2,
166+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
150167
};
151168
}
152169

@@ -156,7 +173,7 @@ nonExhaustiveAfterRestMoreKeys(Map o) {
156173
type=Map<dynamic, dynamic>
157174
*/
158175
switch (o) {
159-
{0: _} /*space={0: (), ...}*/ => 0,
176+
{0: _} /*space={0: ()}*/ => 0,
160177
{0: _, 1: _} /*
161178
error=unreachable,
162179
space={0: (), 1: ()}
@@ -175,7 +192,7 @@ unreachableAfterSameKeys(Map o) {
175192
*/
176193
=>
177194
1,
178-
Map() /*space={...}*/ => 2,
195+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
179196
};
180197
}
181198

@@ -197,9 +214,9 @@ nonExhaustiveAfterSameKeys(Map o) {
197214

198215
reachableAfterRestOnlyDifferentTypes(Map o) {
199216
return /*type=Map<dynamic, dynamic>*/ switch (o) {
200-
<int, String>{...} /*space=<int, String>{...}*/ => 0,
217+
Map<int, String>() /*space=Map<int, String>*/ => 0,
201218
<int, bool>{0: _} /*space=<int, bool>{0: bool}*/ => 1,
202-
Map() /*space={...}*/ => 2,
219+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
203220
};
204221
}
205222

@@ -209,51 +226,56 @@ nonExhaustiveAfterRestOnlyDifferentTypes(Map o) {
209226
type=Map<dynamic, dynamic>
210227
*/
211228
switch (o) {
212-
Map<int, String>() /*space=<int, String>{...}*/ => 0,
229+
Map<int, String>() /*space=Map<int, String>*/ => 0,
213230
<int, bool>{0: _} /*space=<int, bool>{0: bool}*/ => 1,
214231
};
215232
}
216233

217234
reachableAfterRestOnlyEmptyDifferentTypes(Map o) {
218-
return /*type=Map<dynamic, dynamic>*/ switch (o) {
219-
<int, String>{...} /*space=<int, String>{...}*/ => 0,
220-
<int, bool>{} /*space=<int, bool>{}*/ => 1,
221-
Map() /*space={...}*/ => 2,
235+
return /*
236+
fields={isEmpty:bool},
237+
type=Map<dynamic, dynamic>
238+
*/
239+
switch (o) {
240+
Map<int, String>() /*space=Map<int, String>*/ => 0,
241+
Map<int, bool>(isEmpty: true) /*space=Map<int, bool>(isEmpty: true)*/ => 1,
242+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
222243
};
223244
}
224245

225246
nonExhaustiveAfterRestOnlyEmptyDifferentTypes(Map o) {
226247
return /*
227248
error=non-exhaustive:Map<dynamic, dynamic>(),
249+
fields={isEmpty:bool},
228250
type=Map<dynamic, dynamic>
229251
*/
230252
switch (o) {
231-
Map<int, String>() /*space=<int, String>{...}*/ => 0,
232-
<int, bool>{} /*space=<int, bool>{}*/ => 1,
253+
Map<int, String>() /*space=Map<int, String>*/ => 0,
254+
Map<int, bool>(isEmpty: true) /*space=Map<int, bool>(isEmpty: true)*/ => 1,
233255
};
234256
}
235257

236258
reachableAfterRestDifferentTypes(Map o) {
237259
return /*type=Map<dynamic, dynamic>*/ switch (o) {
238-
<int, String>{0: _} /*space=<int, String>{0: String, ...}*/ => 0,
260+
<int, String>{0: _} /*space=<int, String>{0: String}*/ => 0,
239261
<int, bool>{0: _} /*space=<int, bool>{0: bool}*/ => 1,
240-
Map() /*space={...}*/ => 2,
262+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
241263
};
242264
}
243265

244266
nonExhaustiveAfterRestDifferentTypes(Map o) {
245267
return /*type=Map<dynamic, dynamic>*/ switch (o) {
246-
<int, String>{0: _} /*space=<int, String>{0: String, ...}*/ => 0,
268+
<int, String>{0: _} /*space=<int, String>{0: String}*/ => 0,
247269
<int, bool>{0: _} /*space=<int, bool>{0: bool}*/ => 1,
248-
Map() /*space={...}*/ => 2,
270+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
249271
};
250272
}
251273

252274
reachableAfterRestDifferentKeys(Map o) {
253275
return /*type=Map<dynamic, dynamic>*/ switch (o) {
254-
{0: _} /*space={0: (), ...}*/ => 0,
276+
{0: _} /*space={0: ()}*/ => 0,
255277
{1: _} /*space={1: ()}*/ => 1,
256-
Map() /*space={...}*/ => 2,
278+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
257279
};
258280
}
259281

@@ -263,7 +285,7 @@ nonExhaustiveAfterRestDifferentKeys(Map o) {
263285
type=Map<dynamic, dynamic>
264286
*/
265287
switch (o) {
266-
{0: _} /*space={0: (), ...}*/ => 0,
288+
{0: _} /*space={0: ()}*/ => 0,
267289
{1: _} /*space={1: ()}*/ => 1,
268290
};
269291
}
@@ -272,7 +294,7 @@ reachableAfterDifferentKeys(Map o) {
272294
return /*type=Map<dynamic, dynamic>*/ switch (o) {
273295
{0: _} /*space={0: ()}*/ => 0,
274296
{1: _} /*space={1: ()}*/ => 1,
275-
Map() /*space={...}*/ => 2,
297+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
276298
};
277299
}
278300

@@ -291,7 +313,7 @@ reachableAfterDifferentTypes(Map o) {
291313
return /*type=Map<dynamic, dynamic>*/ switch (o) {
292314
<int, String>{0: _} /*space=<int, String>{0: String}*/ => 0,
293315
<int, bool>{0: _} /*space=<int, bool>{0: bool}*/ => 1,
294-
Map() /*space={...}*/ => 2,
316+
Map() /*space=Map<dynamic, dynamic>*/ => 2,
295317
};
296318
}
297319

0 commit comments

Comments
 (0)