Skip to content

Commit 055cf3f

Browse files
authored
#3057. Add switch statement tests (#3121)
Add switch statement tests
1 parent 46d5763 commit 055cf3f

16 files changed

+816
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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 statement: If `N` is a switch statement of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = before(N)`.
8+
/// - For each `C` in `alternatives` with statement body `S`:
9+
/// - If `C` is labelled let
10+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`
11+
/// otherwise let `before(S) = after(E)`.
12+
/// - If the cases are exhaustive, then let `after(N) = break(N)` otherwise let
13+
/// `after(N) = join(after(E), break(N))`.
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+
switch (foo()) {
25+
case 1:
26+
i = 42;
27+
default:
28+
i = 42;
29+
}
30+
}
31+
i; // Definitely unassigned
32+
//^
33+
// [analyzer] unspecified
34+
// [cfe] unspecified
35+
}
36+
37+
void test2(Never n) {
38+
late int i;
39+
if (2 > 1) {
40+
switch (n) {
41+
case 1:
42+
i = 42;
43+
default:
44+
i = 42;
45+
}
46+
}
47+
i; // Definitely unassigned
48+
//^
49+
// [analyzer] unspecified
50+
// [cfe] unspecified
51+
}
52+
53+
void test3<T extends Never>(T n) {
54+
late int i;
55+
if (2 > 1) {
56+
switch (n) {
57+
case 1:
58+
i = 42;
59+
default:
60+
i = 42;
61+
}
62+
}
63+
i; // Definitely unassigned
64+
//^
65+
// [analyzer] unspecified
66+
// [cfe] unspecified
67+
}
68+
69+
main() {
70+
print(test1);
71+
print(test2);
72+
print(test3);
73+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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 statement: If `N` is a switch statement of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = before(N)`.
8+
/// - For each `C` in `alternatives` with statement body `S`:
9+
/// - If `C` is labelled let
10+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`
11+
/// otherwise let `before(S) = after(E)`.
12+
/// - If the cases are exhaustive, then let `after(N) = break(N)` otherwise let
13+
/// `after(N) = join(after(E), break(N))`.
14+
///
15+
/// @description Checks that if `C` is labelled then
16+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`. Test
17+
/// that if `C` is labeled and a variable was assigned in `E` then it is
18+
/// definitely assigned in `S`.
19+
/// @author [email protected]
20+
21+
void main() {
22+
int i;
23+
switch (i = 42) {
24+
label: case 1:
25+
i; // Definitely assigned
26+
default:
27+
}
28+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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 statement: If `N` is a switch statement of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = before(N)`.
8+
/// - For each `C` in `alternatives` with statement body `S`:
9+
/// - If `C` is labelled let
10+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`
11+
/// otherwise let `before(S) = after(E)`.
12+
/// - If the cases are exhaustive, then let `after(N) = break(N)` otherwise let
13+
/// `after(N) = join(after(E), break(N))`.
14+
///
15+
/// @description Checks that if `C` is labelled then
16+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`. Test
17+
/// that if `C` is labeled and a variable was assigned in `N` then it is
18+
/// in a "possibly assigned" state in `S`.
19+
/// @author [email protected]
20+
21+
void test1() {
22+
late int i;
23+
switch (42) {
24+
case 1:
25+
i = 42;
26+
label: case 2:
27+
i; // Possibly assigned
28+
default:
29+
}
30+
}
31+
32+
void test2() {
33+
late int i;
34+
switch (42) {
35+
label: case 1:
36+
i;
37+
case 2:
38+
i = 42;
39+
default:
40+
}
41+
}
42+
43+
void test3() {
44+
late int i;
45+
switch (42) {
46+
label: case 1:
47+
i;
48+
default:
49+
i = 42;
50+
}
51+
}
52+
53+
main() {
54+
test1();
55+
test2();
56+
test3();
57+
}
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 statement: If `N` is a switch statement of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = before(N)`.
8+
/// - For each `C` in `alternatives` with statement body `S`:
9+
/// - If `C` is labelled let
10+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`
11+
/// otherwise let `before(S) = after(E)`.
12+
/// - If the cases are exhaustive, then let `after(N) = break(N)` otherwise let
13+
/// `after(N) = join(after(E), break(N))`.
14+
///
15+
/// @description Checks that if `C` is labelled then
16+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`. Test
17+
/// that if `C` is labeled and a variable was assigned in `N` then it is
18+
/// in a "possibly assigned" state in `S`. Test object-pattern assignment.
19+
/// @author [email protected]
20+
21+
class C {
22+
final int v;
23+
const C(this.v);
24+
}
25+
26+
void test1() {
27+
late int i;
28+
switch (42) {
29+
case 1:
30+
C(v: i) = C(42);
31+
label: case 2:
32+
i; // Possibly assigned
33+
default:
34+
}
35+
}
36+
37+
void test2() {
38+
late int i;
39+
switch (42) {
40+
label: case 1:
41+
i;
42+
case 2:
43+
C(v: i) = C(42);
44+
default:
45+
}
46+
}
47+
48+
void test3() {
49+
late int i;
50+
switch (42) {
51+
label: case 1:
52+
i;
53+
default:
54+
C(v: i) = C(42);
55+
}
56+
}
57+
58+
main() {
59+
test1();
60+
test2();
61+
test3();
62+
}
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 statement: If `N` is a switch statement of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = before(N)`.
8+
/// - For each `C` in `alternatives` with statement body `S`:
9+
/// - If `C` is labelled let
10+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`
11+
/// otherwise let `before(S) = after(E)`.
12+
/// - If the cases are exhaustive, then let `after(N) = break(N)` otherwise let
13+
/// `after(N) = join(after(E), break(N))`.
14+
///
15+
/// @description Checks that if `C` is labelled then
16+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`. Test
17+
/// that if `C` is labeled and a variable was assigned in `N` then it is
18+
/// in a "possibly assigned" state in `S`. Test record-pattern assignment.
19+
/// @author [email protected]
20+
21+
class C {
22+
final int v;
23+
const C(this.v);
24+
}
25+
26+
void test1() {
27+
late int i;
28+
switch (42) {
29+
case 1:
30+
(i,) = (42,);
31+
label: case 2:
32+
i; // Possibly assigned
33+
default:
34+
}
35+
}
36+
37+
void test2() {
38+
late int i;
39+
switch (42) {
40+
label: case 1:
41+
i;
42+
case 2:
43+
(x: i) = (x: 42);
44+
default:
45+
}
46+
}
47+
48+
void test3() {
49+
late int i;
50+
switch (42) {
51+
label: case 1:
52+
i;
53+
default:
54+
(i,) = (42,);
55+
}
56+
}
57+
58+
main() {
59+
test1();
60+
test2();
61+
test3();
62+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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 statement: If `N` is a switch statement of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = before(N)`.
8+
/// - For each `C` in `alternatives` with statement body `S`:
9+
/// - If `C` is labelled let
10+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`
11+
/// otherwise let `before(S) = after(E)`.
12+
/// - If the cases are exhaustive, then let `after(N) = break(N)` otherwise let
13+
/// `after(N) = join(after(E), break(N))`.
14+
///
15+
/// @description Checks that if `C` is labelled then
16+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`. Test
17+
/// that if `C` is labeled and a variable was assigned in `N` then it is in a
18+
/// "possibly assigned" state in `after(N)`.
19+
/// @author [email protected]
20+
21+
test() {
22+
late int i;
23+
switch (42) {
24+
label: case 1:
25+
break;
26+
i = 42;
27+
default:
28+
}
29+
i; // Possibly assigned
30+
}
31+
32+
main() {
33+
print(test);
34+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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 statement: If `N` is a switch statement of the form
6+
/// `switch (E) {alternatives}` then:
7+
/// - Let `before(E) = before(N)`.
8+
/// - For each `C` in `alternatives` with statement body `S`:
9+
/// - If `C` is labelled let
10+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`
11+
/// otherwise let `before(S) = after(E)`.
12+
/// - If the cases are exhaustive, then let `after(N) = break(N)` otherwise let
13+
/// `after(N) = join(after(E), break(N))`.
14+
///
15+
/// @description Checks that if a promoted variable was captured in `E` then it
16+
/// is demoted in `S`.
17+
/// @author [email protected]
18+
19+
void test(int? n) {
20+
if (n != null) { // n promoted to int
21+
switch ((){n = 42;}) { // n demoted to int?
22+
label: case 1: // ignore: constant_pattern_never_matches_value_type
23+
n.isEven;
24+
// ^^^^^^
25+
// [analyzer] unspecified
26+
// [cfe] unspecified
27+
case 2: // ignore: constant_pattern_never_matches_value_type
28+
n.isEven;
29+
// ^^^^^^
30+
// [analyzer] unspecified
31+
// [cfe] unspecified
32+
default:
33+
n.isEven;
34+
// ^^^^^^
35+
// [analyzer] unspecified
36+
// [cfe] unspecified
37+
}
38+
}
39+
}
40+
41+
main() {
42+
print(test);
43+
}

0 commit comments

Comments
 (0)