Skip to content

Commit b02ea05

Browse files
authored
#3057. Add switch-expression tests (#3135)
Add switch-expression tests
1 parent c6afee1 commit b02ea05

7 files changed

+440
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) 2025, 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: If `N` is a switch expression of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = split(before(N))`.
8+
/// - For each case `Cj` in `alternatives` with expression `Ej`, for `j` in
9+
/// `1 .. k`:
10+
/// - Let `before(Ej) = after(E)`.
11+
/// - Let `after(N) = join(after(E1), after(E2), .. after(Ek))`.
12+
/// TODO (sgrekhov): there is no switch expression in the flow analysis spec yet
13+
/// (April 2025). Update the assertion after spec update.
14+
///
15+
/// @description Checks that if `E` has type `Never` then all `alternatives` are
16+
/// unreachable.
17+
/// @author [email protected]
18+
19+
Never foo() => throw "Never";
20+
21+
void test1() {
22+
late int i;
23+
if (2 > 1) {
24+
var x = switch (foo()) {
25+
1 => (i = 42),
26+
_ => (i = 42)
27+
};
28+
}
29+
i; // Definitely unassigned
30+
//^
31+
// [analyzer] unspecified
32+
// [cfe] unspecified
33+
}
34+
35+
void test2(Never n) {
36+
late int i;
37+
if (2 > 1) {
38+
var x = switch (n) {
39+
1 => (i = 42),
40+
_ => (i = 42)
41+
};
42+
}
43+
i; // Definitely unassigned
44+
//^
45+
// [analyzer] unspecified
46+
// [cfe] unspecified
47+
}
48+
49+
void test3<T extends Never>(T n) {
50+
late int i;
51+
if (2 > 1) {
52+
var x = switch (n) {
53+
1 => (i = 42),
54+
_ => (i = 42)
55+
};
56+
}
57+
i; // Definitely unassigned
58+
//^
59+
// [analyzer] unspecified
60+
// [cfe] unspecified
61+
}
62+
63+
main() {
64+
print(test1);
65+
print(test2);
66+
print(test3);
67+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) 2025, 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: If `N` is a switch expression of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = split(before(N))`.
8+
/// - For each case `Cj` in `alternatives` with expression `Ej`, for `j` in
9+
/// `1 .. k`:
10+
/// - Let `before(Ej) = after(E)`.
11+
/// - Let `after(N) = join(after(E1), after(E2), .. after(Ek))`.
12+
/// TODO (sgrekhov): there is no switch expression in the flow analysis spec yet
13+
/// (April 2025). Update the assertion after spec update.
14+
///
15+
/// @description Checks that `before(S) = after(E)`. Test that if a variable was
16+
/// assigned in `E` then it is definitely assigned in `S`.
17+
/// @author [email protected]
18+
/// @issue 56338
19+
20+
class C {
21+
int v;
22+
C(this.v);
23+
}
24+
25+
void test1() {
26+
int i;
27+
var x = switch (i = 42) {
28+
1 => i, // Definitely assigned
29+
_ => 42
30+
};
31+
}
32+
33+
void test2() {
34+
int i;
35+
var x = switch ((i,) = (42,)) {
36+
1 => i, // ignore: constant_pattern_never_matches_value_type
37+
_ => 42
38+
};
39+
}
40+
41+
void test3() {
42+
int i;
43+
var x = switch ((x: i) = (x: 42)) {
44+
1 => i, // ignore: constant_pattern_never_matches_value_type
45+
_ => 42
46+
};
47+
}
48+
49+
void test4() {
50+
int i;
51+
var x = switch (C(v: i) = C(42)) {
52+
1 => i, // ignore: constant_pattern_never_matches_value_type
53+
_ => 42
54+
};
55+
}
56+
57+
main() {
58+
test1();
59+
test2();
60+
test3();
61+
test4();
62+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) 2025, 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: If `N` is a switch expression of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = split(before(N))`.
8+
/// - For each case `Cj` in `alternatives` with expression `Ej`, for `j` in
9+
/// `1 .. k`:
10+
/// - Let `before(Ej) = after(E)`.
11+
/// - Let `after(N) = join(after(E1), after(E2), .. after(Ek))`.
12+
/// TODO (sgrekhov): there is no switch expression in the flow analysis spec yet
13+
/// (April 2025). Update the assertion after spec update.
14+
///
15+
/// @description Checks that `before(S) = after(E)`. Test that if a variable was
16+
/// assigned in `N` then it is definitely unassigned in all others `S`.
17+
/// @author [email protected]
18+
19+
void test1() {
20+
late int i;
21+
var x = switch (42) {
22+
1 => i = 42,
23+
2 => i, // Definitely unassigned
24+
// ^
25+
// [analyzer] unspecified
26+
// [cfe] unspecified
27+
_ => i
28+
// ^
29+
// [analyzer] unspecified
30+
// [cfe] unspecified
31+
};
32+
}
33+
34+
void test2() {
35+
late int i;
36+
var x = switch (42) {
37+
1 => i,
38+
// ^
39+
// [analyzer] unspecified
40+
// [cfe] unspecified
41+
2 => i,
42+
// ^
43+
// [analyzer] unspecified
44+
// [cfe] unspecified
45+
_ => i = 42
46+
};
47+
}
48+
49+
main() {
50+
print(test1);
51+
print(test2);
52+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright (c) 2025, 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: If `N` is a switch expression of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = split(before(N))`.
8+
/// - For each case `Cj` in `alternatives` with expression `Ej`, for `j` in
9+
/// `1 .. k`:
10+
/// - Let `before(Ej) = after(E)`.
11+
/// - Let `after(N) = join(after(E1), after(E2), .. after(Ek))`.
12+
/// TODO (sgrekhov): there is no switch expression in the flow analysis spec yet
13+
/// (April 2025). Update the assertion after spec update.
14+
///
15+
/// @description Checks that if `C` is not labelled then `before(S) = after(E)`.
16+
/// Test that if `C` is not labeled and a promoted variable was captured in `E`
17+
/// then it is demoted in `S`.
18+
/// @author [email protected]
19+
20+
class C {
21+
int v;
22+
C(this.v);
23+
}
24+
25+
void test1(int? n) {
26+
if (n != null) { // `n` promoted to `int`
27+
var x = switch ((){n = 42; return 1;}()) { // `n` demoted to `int?`
28+
1 => n.isEven,
29+
// ^^^^^^
30+
// [analyzer] unspecified
31+
// [cfe] unspecified
32+
_ => false
33+
};
34+
}
35+
}
36+
37+
void test2(int? n) {
38+
if (n != null) {
39+
var x = switch ((){(n,) = (42,); return 1;}()) {
40+
1 => n.isEven,
41+
// ^^^^^^
42+
// [analyzer] unspecified
43+
// [cfe] unspecified
44+
_ => false
45+
};
46+
}
47+
}
48+
49+
void test3(int? n) {
50+
if (n != null) {
51+
var x = switch ((){(x: n) = (x: 42); return 1;}()) {
52+
1 => n.isEven,
53+
// ^^^^^^
54+
// [analyzer] unspecified
55+
// [cfe] unspecified
56+
_ => false
57+
};
58+
}
59+
}
60+
61+
void test4(int? n) {
62+
if (n != null) {
63+
var x = switch ((){C(v: n) = C(42); return 1;}()) {
64+
1 => n.isEven,
65+
// ^^^^^^
66+
// [analyzer] unspecified
67+
// [cfe] unspecified
68+
_ => false
69+
};
70+
}
71+
}
72+
73+
main() {
74+
print(test1);
75+
print(test2);
76+
print(test3);
77+
print(test4);
78+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) 2025, 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: If `N` is a switch expression of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = split(before(N))`.
8+
/// - For each case `Cj` in `alternatives` with expression `Ej`, for `j` in
9+
/// `1 .. k`:
10+
/// - Let `before(Ej) = after(E)`.
11+
/// - Let `after(N) = join(after(E1), after(E2), .. after(Ek))`.
12+
/// TODO (sgrekhov): there is no switch expression in the flow analysis spec yet
13+
/// (April 2025). Update the assertion after spec update.
14+
///
15+
/// @description Checks that `before(S) = after(E)`. Test that if a promoted
16+
/// variable was captured in another `C` then it is not demoted in `S`.
17+
/// @author [email protected]
18+
19+
class C {
20+
int v;
21+
C(this.v);
22+
}
23+
24+
void test1(int? n) {
25+
if (n != null) { // n promoted to int
26+
var x = switch (42) {
27+
1 => () {n = 42;},
28+
2 => () {(n,) = (42,);},
29+
3 => () {(x: n) = (x: 42);},
30+
4 => () {C(v: n) = C(42);},
31+
5 => n.isEven,
32+
_ => null
33+
};
34+
}
35+
}
36+
37+
void test2(int? n) {
38+
if (n != null) {
39+
var x = switch (42) {
40+
0 => n.isEven,
41+
1 => () {n = 42;},
42+
2 => () {(n,) = (42,);},
43+
3 => () {(x: n) = (x: 42);},
44+
4 => () {C(v: n) = C(42);},
45+
_ => null
46+
};
47+
}
48+
}
49+
50+
void test3(int? n) {
51+
if (n != null) {
52+
var x = switch (42) {
53+
0 => n.isEven,
54+
1 => () {n = 42;},
55+
2 => () {(n,) = (42,);},
56+
3 => () {(x: n) = (x: 42);},
57+
_ => () {C(v: n) = C(42);}
58+
};
59+
}
60+
}
61+
62+
void test4(int? n) {
63+
if (n != null) {
64+
var x = switch (42) {
65+
1 => () {n = 42;},
66+
2 => () {(n,) = (42,);},
67+
3 => () {(x: n) = (x: 42);},
68+
4 => () {C(v: n) = C(42);},
69+
_ => n.isEven
70+
};
71+
}
72+
}
73+
74+
main() {
75+
test1(1);
76+
test2(2);
77+
test3(3);
78+
test4(4);
79+
}

0 commit comments

Comments
 (0)