Skip to content

Commit 03a2b9c

Browse files
committed
dart-lang#2420. Add extension types exhaustiveness tests. Lists
1 parent 3734cda commit 03a2b9c

11 files changed

+832
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Switch expression with a list as a matched type can be exhaustive
6+
///
7+
/// @description Check that it is no compile-time error if a matched type of a
8+
/// switch expression is an extension type with a `List` as a representation
9+
/// type and all cases are exhaustive. Test a rest element at the end of the
10+
/// list pattern
11+
/// @author [email protected]
12+
13+
// SharedOptions=--enable-experiment=inline-class
14+
15+
import "../../Utils/expect.dart";
16+
17+
extension type ET1<T>(List<T> _) {}
18+
extension type ET2<T>(List<T> _) implements List<T> {}
19+
20+
String test1_1(ET1<int> l) =>
21+
switch (l) {
22+
<int?>[] => "0",
23+
[_] => "1",
24+
[_, _] => "2",
25+
[_, _, ...] => "2+"
26+
};
27+
28+
String test1_2(ET2<int> l) =>
29+
switch (l) {
30+
<int?>[] => "0",
31+
[_] => "1",
32+
[_, _] => "2",
33+
[_, _, ...] => "2+"
34+
};
35+
36+
String test2_1(ET1<bool> l) =>
37+
switch (l) {
38+
[] => "0",
39+
[true] => "1_1",
40+
[false] => "1_2",
41+
[_, true] => "2_1",
42+
[_, false] => "2_2",
43+
[_, true, ...var r1] => "3_1",
44+
[_, false, ...final r2] => "3_2"
45+
};
46+
47+
String test2_2(ET2<bool> l) =>
48+
switch (l) {
49+
[] => "0",
50+
[true] => "1_1",
51+
[false] => "1_2",
52+
[_, true] => "2_1",
53+
[_, false] => "2_2",
54+
[_, true, ...var r1] => "3_1",
55+
[_, false, ...final r2] => "3_2"
56+
};
57+
58+
main() {
59+
Expect.equals("0", test1_1(ET1([])));
60+
Expect.equals("1", test1_1(ET1([1])));
61+
Expect.equals("2", test1_1(ET1<int>([1, 2])));
62+
Expect.equals("2+", test1_1(ET1([1, 2, 3])));
63+
64+
Expect.equals("0", test1_2(ET2([])));
65+
Expect.equals("1", test1_2(ET2([1])));
66+
Expect.equals("2", test1_2(ET2<int>([1, 2])));
67+
Expect.equals("2+", test1_2(ET2([1, 2, 3])));
68+
69+
Expect.equals("0", test2_1(ET1([])));
70+
Expect.equals("1_1", test2_1(ET1([true])));
71+
Expect.equals("1_2", test2_1(ET1([false])));
72+
Expect.equals("2_1", test2_1(ET1([true, true])));
73+
Expect.equals("2_2", test2_1(ET1([true, false])));
74+
Expect.equals("3_1", test2_1(ET1([true, true, false])));
75+
Expect.equals("3_2", test2_1(ET1([true, false, false])));
76+
77+
Expect.equals("0", test2_2(ET2([])));
78+
Expect.equals("1_1", test2_2(ET2([true])));
79+
Expect.equals("1_2", test2_2(ET2([false])));
80+
Expect.equals("2_1", test2_2(ET2([true, true])));
81+
Expect.equals("2_2", test2_2(ET2([true, false])));
82+
Expect.equals("3_1", test2_2(ET2([true, true, false])));
83+
Expect.equals("3_2", test2_2(ET2([true, false, false])));
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Switch expression with a list as a matched type can be exhaustive
6+
///
7+
/// @description Check that it is no compile-time error if a matched type of a
8+
/// switch expression is an extension type with a `List` as a representation
9+
/// type and all cases are exhaustive. Test a rest element at the middle of the
10+
/// list pattern
11+
/// @author [email protected]
12+
13+
// SharedOptions=--enable-experiment=inline-class
14+
15+
import "../../Utils/expect.dart";
16+
17+
extension type ET1<T>(List<T> _) {}
18+
extension type ET2<T>(List<T> _) implements List<T> {}
19+
20+
String test1_1(ET1<int> l) =>
21+
switch (l) {
22+
[] => "0",
23+
<int?>[_] => "1",
24+
[_, _] => "2",
25+
[_, ..., _] => "2+"
26+
};
27+
28+
String test1_2(ET2<int> l) =>
29+
switch (l) {
30+
[] => "0",
31+
<int?>[_] => "1",
32+
[_, _] => "2",
33+
[_, ..., _] => "2+"
34+
};
35+
36+
String test2_1(ET1<bool> l) =>
37+
switch (l) {
38+
[] => "0",
39+
[true] => "1_1",
40+
[false] => "1_2",
41+
[_, true] => "2_1",
42+
[_, false] => "2_2",
43+
[_, ... var r1, true] => "3_1",
44+
[_, ... final r2, false] => "3_2"
45+
};
46+
47+
String test2_2(ET2<bool> l) =>
48+
switch (l) {
49+
[] => "0",
50+
[true] => "1_1",
51+
[false] => "1_2",
52+
[_, true] => "2_1",
53+
[_, false] => "2_2",
54+
[_, ... var r1, true] => "3_1",
55+
[_, ... final r2, false] => "3_2"
56+
};
57+
58+
main() {
59+
Expect.equals("0", test1_1(ET1([])));
60+
Expect.equals("1", test1_1(ET1([1])));
61+
Expect.equals("2", test1_1(ET1<int>([1, 2])));
62+
Expect.equals("2+", test1_1(ET1([1, 2, 3])));
63+
64+
Expect.equals("0", test1_2(ET2([])));
65+
Expect.equals("1", test1_2(ET2([1])));
66+
Expect.equals("2", test1_2(ET2<int>([1, 2])));
67+
Expect.equals("2+", test1_2(ET2([1, 2, 3])));
68+
69+
Expect.equals("0", test2_1(ET1([])));
70+
Expect.equals("1_1", test2_1(ET1([true])));
71+
Expect.equals("1_2", test2_1(ET1([false])));
72+
Expect.equals("2_1", test2_1(ET1([true, true])));
73+
Expect.equals("2_2", test2_1(ET1([true, false])));
74+
Expect.equals("3_1", test2_1(ET1([true, true, true])));
75+
Expect.equals("3_2", test2_1(ET1([true, false, false])));
76+
77+
Expect.equals("0", test2_2(ET2([])));
78+
Expect.equals("1_1", test2_2(ET2([true])));
79+
Expect.equals("1_2", test2_2(ET2([false])));
80+
Expect.equals("2_1", test2_2(ET2([true, true])));
81+
Expect.equals("2_2", test2_2(ET2([true, false])));
82+
Expect.equals("3_1", test2_2(ET2([true, true, true])));
83+
Expect.equals("3_2", test2_2(ET2([true, false, false])));
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Switch expression with a list as a matched type can be exhaustive
6+
///
7+
/// @description Check that it is no compile-time error if a matched type of a
8+
/// switch expression is an extension type with a `List` as a representation
9+
/// type and all cases are exhaustive. Test rest element at the beginning of
10+
/// the list pattern
11+
/// @author [email protected]
12+
13+
// SharedOptions=--enable-experiment=inline-class
14+
15+
import "../../Utils/expect.dart";
16+
17+
extension type ET1<T>(List<T> _) {}
18+
extension type ET2<T>(List<T> _) implements List<T> {}
19+
20+
String test1_1(ET1<int> l) =>
21+
switch (l) {
22+
[] => "0",
23+
[_] => "1",
24+
[_, _] => "2",
25+
<int?>[..., _, _] => "2+"
26+
};
27+
28+
String test1_2(ET2<int> l) =>
29+
switch (l) {
30+
[] => "0",
31+
[_] => "1",
32+
[_, _] => "2",
33+
<int?>[..., _, _] => "2+"
34+
};
35+
36+
String test2_1(ET1<bool> l) =>
37+
switch (l) {
38+
[] => "0",
39+
[true] => "1_1",
40+
[false] => "1_2",
41+
[_, true] => "2_1",
42+
[_, false] => "2_2",
43+
[... var r1, true] => "3_1",
44+
[... final r2, false] => "3_2"
45+
};
46+
47+
String test2_2(ET2<bool> l) =>
48+
switch (l) {
49+
[] => "0",
50+
[true] => "1_1",
51+
[false] => "1_2",
52+
[_, true] => "2_1",
53+
[_, false] => "2_2",
54+
[... var r1, true] => "3_1",
55+
[... final r2, false] => "3_2"
56+
};
57+
58+
main() {
59+
Expect.equals("0", test1_1(ET1([])));
60+
Expect.equals("1", test1_1(ET1([1])));
61+
Expect.equals("2", test1_1(ET1([1, 2])));
62+
Expect.equals("2+", test1_1(ET1([1, 2, 3])));
63+
64+
Expect.equals("0", test1_2(ET2([])));
65+
Expect.equals("1", test1_2(ET2([1])));
66+
Expect.equals("2", test1_2(ET2([1, 2])));
67+
Expect.equals("2+", test1_2(ET2([1, 2, 3])));
68+
69+
Expect.equals("0", test2_1(ET1([])));
70+
Expect.equals("1_1", test2_1(ET1([true])));
71+
Expect.equals("1_2", test2_1(ET1([false])));
72+
Expect.equals("2_1", test2_1(ET1([true, true])));
73+
Expect.equals("2_2", test2_1(ET1([true, false])));
74+
Expect.equals("3_1", test2_1(ET1([true, true, true])));
75+
Expect.equals("3_2", test2_1(ET1([true, false, false])));
76+
77+
Expect.equals("0", test2_2(ET2([])));
78+
Expect.equals("1_1", test2_2(ET2([true])));
79+
Expect.equals("1_2", test2_2(ET2([false])));
80+
Expect.equals("2_1", test2_2(ET2([true, true])));
81+
Expect.equals("2_2", test2_2(ET2([true, false])));
82+
Expect.equals("3_1", test2_2(ET2([true, true, true])));
83+
Expect.equals("3_2", test2_2(ET2([true, false, false])));
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Switch statements with a list as a matched type can never be
6+
/// exhaustive
7+
///
8+
/// @description Check that exhaustiveness check is not performed for a switch
9+
/// statement with a list as a matched type
10+
/// @author [email protected]
11+
12+
extension type ET1<T>(List<T> _) {}
13+
extension type ET2<T>(List<T> _) implements List<T> {}
14+
15+
String test1(ET1<bool> l) {
16+
// ^^^^^
17+
// [analyzer] unspecified
18+
// [cfe] unspecified
19+
switch (l) {
20+
case []:
21+
case [_]:
22+
case [_, _]:
23+
case [_, _, ...]:
24+
return "ok";
25+
}
26+
// There is no return statement here, and static analysis doesn't know if the
27+
// switch statement exhaustive or not, so an error above occurs because function
28+
// return type cannot be null
29+
}
30+
31+
String test2(ET2<bool> l) {
32+
// ^^^^^
33+
// [analyzer] unspecified
34+
// [cfe] unspecified
35+
switch (l) {
36+
case []:
37+
case [_]:
38+
case [_, _]:
39+
case [_, _, ...]:
40+
return "ok";
41+
}
42+
}
43+
44+
main() {
45+
test1(ET1([]));
46+
test2(ET2([]));
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Switch expression with a list as a matched type can be exhaustive
6+
///
7+
/// @description Check that it is a compile-time error if a matched type of a
8+
/// switch expression is a list and cases are not exhaustive.
9+
/// @author [email protected]
10+
11+
extension type ET1<T>(List<T> _) {}
12+
extension type ET2<T>(List<T> _) implements List<T> {}
13+
14+
String test1_1(ET1<int> l) =>
15+
switch (l) {
16+
//^^^^^^
17+
// [analyzer] unspecified
18+
// [cfe] unspecified
19+
<String>[] => "0",
20+
[_] => "1",
21+
[_, _] => "2",
22+
[_, _, ...] => "2+"
23+
};
24+
25+
String test1_2(ET2<int> l) =>
26+
switch (l) {
27+
//^^^^^^
28+
// [analyzer] unspecified
29+
// [cfe] unspecified
30+
<String>[] => "0",
31+
[_] => "1",
32+
[_, _] => "2",
33+
[_, _, ...] => "2+"
34+
};
35+
36+
String test2_1(ET1<int> l) =>
37+
switch (l) {
38+
//^^^^^^
39+
// [analyzer] unspecified
40+
// [cfe] unspecified
41+
[] => "0",
42+
<String>[_] => "1",
43+
[_, _] => "2",
44+
[_, ..., _] => "2+"
45+
};
46+
47+
String test2_2(ET2<int> l) =>
48+
switch (l) {
49+
//^^^^^^
50+
// [analyzer] unspecified
51+
// [cfe] unspecified
52+
[] => "0",
53+
<String>[_] => "1",
54+
[_, _] => "2",
55+
[_, ..., _] => "2+"
56+
};
57+
58+
String test3_1(ET1<int> l) =>
59+
switch (l) {
60+
//^^^^^^
61+
// [analyzer] unspecified
62+
// [cfe] unspecified
63+
[] => "0",
64+
[_] => "1",
65+
[_, _] => "2",
66+
<String>[..., _, _] => "2+"
67+
};
68+
69+
String test3_2(ET2<int> l) =>
70+
switch (l) {
71+
//^^^^^^
72+
// [analyzer] unspecified
73+
// [cfe] unspecified
74+
[] => "0",
75+
[_] => "1",
76+
[_, _] => "2",
77+
<String>[..., _, _] => "2+"
78+
};
79+
80+
main() {
81+
test1_1(ET1([]));
82+
test1_2(ET2([]));
83+
test2_1(ET1([]));
84+
test2_2(ET2([]));
85+
test3_1(ET1([]));
86+
test3_2(ET2([]));
87+
}

0 commit comments

Comments
 (0)