Skip to content

Commit e8f837d

Browse files
authored
#3057. Add return statement in loops tests (#3158)
Add return statement in loops tests
1 parent 3423649 commit e8f837d

6 files changed

+219
-3
lines changed
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 do while statement: If `N` is a do while statement of the form
6+
/// `do S while (E)` then:
7+
/// - Let `before(S) = conservativeJoin(before(N), assignedIn(N), capturedIn(N))`.
8+
/// - Let `before(E) = join(after(S), continue(N))`
9+
/// - Let `after(N) = join(false(E), break(S))`
10+
///
11+
/// @description Checks that `after(N) = join(false(E), break(S))`. Test that an
12+
/// assignment in `S` after `return` is unreachable.
13+
/// @author [email protected]
14+
15+
main() {
16+
late int i;
17+
if (1 > 2) {
18+
do {
19+
return;
20+
i = 42;
21+
} while (false);
22+
i; // Ok. `after(N)` is unreachable
23+
}
24+
i; // Definitely unassigned
25+
//^
26+
// [analyzer] unspecified
27+
// [cfe] unspecified
28+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 for statement: If `N` is a for statement of the form
6+
/// `for (D; C; U) S,` then:
7+
/// - Let `before(D) = before(N)`.
8+
/// - Let `before(C) = conservativeJoin(after(D), assignedIn(N), capturedIn(N))`
9+
/// - Let `before(S) = split(true(C))`.
10+
/// - Let `before(U) = merge(after(S), continue(S))`.
11+
/// - Let `after(N) = inheritTested(join(false(C), unsplit(break(S))), after(U))`
12+
///
13+
/// @description Checks that
14+
/// `before(C) = conservativeJoin(after(D), assignedIn(N), capturedIn(N))`. Test
15+
/// that an assignment in `S` after `return` is unreachable.
16+
/// @author [email protected]
17+
18+
test1() {
19+
late int i;
20+
if (2 < 1) {
21+
for (;;) {
22+
return;
23+
i = 42;
24+
}
25+
i; // Ok. `after(N)` is unreachable
26+
}
27+
i; // Definitely unassigned
28+
//^
29+
// [analyzer] unspecified
30+
// [cfe] unspecified
31+
}
32+
33+
test2() {
34+
late int i;
35+
if (2 < 1) {
36+
for (int j = 0; j < 1;) {
37+
return;
38+
i = 42;
39+
}
40+
i; // Ok. `after(N)` is unreachable
41+
}
42+
i; // Possibly assigned
43+
}
44+
45+
main() {
46+
print(test1);
47+
print(test2);
48+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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 for each statement: If `N` is a for statement of the form
6+
/// `for (T X in E) S`, `for (var X in E) S`, or `for (X in E) S`, then:
7+
/// - Let `before(E) = before(N)`
8+
/// - Let `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`
9+
/// - Let `after(N) = join(before(S), break(S))`
10+
///
11+
/// @description Checks that
12+
/// `before(S) = conservativeJoin(after(E), assignedIn(N), capturedIn(N))`. Test
13+
/// that if there is an assignment in `S` (even after the `return` statement)
14+
/// then in `after(N)` the variable is "possibly assigned".
15+
/// @author [email protected]
16+
17+
test() {
18+
late int i;
19+
if (2 > 1) {
20+
for (var j in []) {
21+
return;
22+
i = 42;
23+
}
24+
i; // Possibly assigned. See https://github.com/dart-lang/sdk/issues/42232#issuecomment-690681385
25+
}
26+
i; // Possibly assigned
27+
}
28+
29+
main() {
30+
print(test);
31+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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 while statement: If `N` is a while statement of the form
6+
/// `while (E) S` then:
7+
/// - Let `before(E) = conservativeJoin(before(N), assignedIn(N), capturedIn(N))`
8+
/// - Let `before(S) = split(true(E))`.
9+
/// - Let `after(N) = inheritTested(join(false(E), unsplit(break(S))), after(S))`
10+
///
11+
/// @description Checks that
12+
/// `before(E) = conservativeJoin(before(N), assignedIn(N), capturedIn(N))`.
13+
/// Test if there is an assignment in `S` (even after the `return` statement)
14+
/// then `after(N)` the variable is "possibly assigned".
15+
/// @author [email protected]
16+
17+
test1() {
18+
late int i;
19+
if (1 > 2) {
20+
while (2 > 1) {
21+
return;
22+
i = 42;
23+
}
24+
i; // Possibly assigned. See https://github.com/dart-lang/sdk/issues/42232#issuecomment-690681385
25+
}
26+
i; // Possibly assigned.
27+
}
28+
29+
test2() {
30+
late int i;
31+
if (1 > 2) {
32+
while (true) {
33+
return;
34+
i = 42;
35+
}
36+
i; // Possibly assigned and dead code
37+
}
38+
i; // Definitely unassigned.
39+
//^
40+
// [analyzer] unspecified
41+
// [cfe] unspecified
42+
}
43+
44+
main() {
45+
print(test1);
46+
print(test2);
47+
}

TypeSystem/flow-analysis/reachability_while_A03_t01.dart

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
/// - Let `before(S) = split(true(E))`.
99
/// - Let `after(N) = inheritTested(join(false(E), unsplit(break(S))), after(S))`
1010
///
11-
/// @description Checks that if `E` is not a boolean literal flow analysis
12-
/// detects assignment in `S`.
11+
/// @description Checks that if `E` is a boolean `true` literal and there is no
12+
/// reachable `break` in `S` then `after(N) is unreachable.
1313
/// @author [email protected]
1414
15-
main() {
15+
test1() {
1616
late int i;
1717
if (1 > 2) {
1818
while (true) {
@@ -27,3 +27,38 @@ main() {
2727
// [analyzer] unspecified
2828
// [cfe] unspecified
2929
}
30+
31+
test2() {
32+
late int i;
33+
if (1 > 2) {
34+
while (true) {
35+
if (false) {
36+
return;
37+
}
38+
}
39+
i = 42;
40+
}
41+
i; // Definitely unassigned
42+
//^
43+
// [analyzer] unspecified
44+
// [cfe] unspecified
45+
}
46+
47+
test3() {
48+
late int i;
49+
if (1 > 2) {
50+
while (true) {
51+
return;
52+
}
53+
i = 42;
54+
}
55+
i; // Definitely unassigned
56+
//^
57+
// [analyzer] unspecified
58+
// [cfe] unspecified
59+
}
60+
61+
main() {
62+
print(test1);
63+
print(test2);
64+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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 while statement: If `N` is a while statement of the form
6+
/// `while (E) S` then:
7+
/// - Let `before(E) = conservativeJoin(before(N), assignedIn(N), capturedIn(N))`
8+
/// - Let `before(S) = split(true(E))`.
9+
/// - Let `after(N) = inheritTested(join(false(E), unsplit(break(S))), after(S))`
10+
///
11+
/// @description Checks that if `E` is a boolean `true` literal and there is no
12+
/// reachable `break` in `S` then `after(N)` is unreachable.
13+
/// @author [email protected]
14+
15+
main() {
16+
late int i;
17+
if (1 > 2) {
18+
while (true) {
19+
continue;
20+
}
21+
i = 42; // Dead code
22+
}
23+
i; // Definitely unassigned
24+
//^
25+
// [analyzer] unspecified
26+
// [cfe] unspecified
27+
}

0 commit comments

Comments
 (0)