Skip to content

Commit 4ebc13c

Browse files
authored
#3057. Add more flow analysis tests for while loop (#3141)
1 parent 8f94665 commit 4ebc13c

6 files changed

+293
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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 a promoted variable is captured in `S` it is
12+
/// demoted in `E`.
13+
/// @author [email protected]
14+
15+
class C {
16+
int v;
17+
C(this.v);
18+
}
19+
20+
test1(int? n) {
21+
if (n != null) { // `n` promoted to `int`
22+
while (n.isEven) {
23+
// ^^^^^^
24+
// [analyzer] unspecified
25+
// [cfe] unspecified
26+
() {
27+
n = 42; // `n` demoted to `int?`
28+
};
29+
}
30+
}
31+
}
32+
33+
test2(int? n) {
34+
if (n != null) {
35+
while (n.isEven) {
36+
// ^^^^^^
37+
// [analyzer] unspecified
38+
// [cfe] unspecified
39+
() {
40+
(n,) = (42,);
41+
};
42+
}
43+
}
44+
}
45+
46+
test3(int? n) {
47+
if (n != null) {
48+
while (n.isEven) {
49+
// ^^^^^^
50+
// [analyzer] unspecified
51+
// [cfe] unspecified
52+
() {
53+
(x: n) = (x: 42);
54+
};
55+
}
56+
}
57+
}
58+
59+
test4(int? n) {
60+
if (n != null) {
61+
while (n.isEven) {
62+
// ^^^^^^
63+
// [analyzer] unspecified
64+
// [cfe] unspecified
65+
() {
66+
C(v: n) = C(42);
67+
};
68+
}
69+
}
70+
}
71+
72+
main() {
73+
print(test1);
74+
print(test2);
75+
print(test3);
76+
print(test4);
77+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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 a promoted variable is captured in `E` it is
12+
/// demoted in `S`.
13+
/// @author [email protected]
14+
15+
class C {
16+
int v;
17+
C(this.v);
18+
}
19+
20+
test1(int? n) {
21+
if (n != null) { // `n` promoted to `int`
22+
while ((){n = 42; return false;}()) { // `n` demoted to `int?`
23+
n.isEven;
24+
// ^^^^^^
25+
// [analyzer] unspecified
26+
// [cfe] unspecified
27+
}
28+
}
29+
}
30+
31+
test2(int? n) {
32+
if (n != null) {
33+
while ((){(n,) = (42,); return false;}()) {
34+
n.isEven;
35+
// ^^^^^^
36+
// [analyzer] unspecified
37+
// [cfe] unspecified
38+
}
39+
}
40+
}
41+
42+
test3(int? n) {
43+
if (n != null) {
44+
while ((){(x: n) = (x: 42); return false;}()) {
45+
n.isEven;
46+
// ^^^^^^
47+
// [analyzer] unspecified
48+
// [cfe] unspecified
49+
}
50+
}
51+
}
52+
53+
test4(int? n) {
54+
if (n != null) {
55+
while ((){C(v: n) = C(42); return false;}()) {
56+
n.isEven;
57+
// ^^^^^^
58+
// [analyzer] unspecified
59+
// [cfe] unspecified
60+
}
61+
}
62+
}
63+
64+
main() {
65+
print(test1);
66+
print(test2);
67+
print(test3);
68+
print(test4);
69+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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 a type `T` is made a type of interest in
12+
/// `before(N)` then it can be promoted in `E`, `S` and `after(N)`.
13+
/// @author [email protected]
14+
15+
class S {}
16+
17+
class T extends S {
18+
int answer() => 42;
19+
}
20+
21+
test1() {
22+
S s = S();
23+
if (s is T) {} // make `T` a type of interest
24+
while ([s = T(), s.answer()] == []) {}
25+
}
26+
27+
test2() {
28+
S s = S();
29+
if (s is T) {}
30+
while (1 > 2) {
31+
s = T(); // No error
32+
s.answer();
33+
}
34+
}
35+
36+
test3() {
37+
S s = S();
38+
if (s is T) {} // Make T a type of interest
39+
while (1 > 2) {
40+
}
41+
s = T();
42+
s.answer();
43+
}
44+
45+
main() {
46+
test1();
47+
test2();
48+
test3();
49+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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 a type `T` is made a type of interest in `E`
12+
/// then it can be promoted in `S` and `after(N)`.
13+
/// @author [email protected]
14+
15+
class S {}
16+
17+
class T extends S {
18+
int answer() => 42;
19+
}
20+
21+
test1() {
22+
S s = S();
23+
while (s is T) { // make `T` a type of interest
24+
s = T();
25+
s.answer();
26+
}
27+
}
28+
29+
test2() {
30+
S s = S();
31+
while (s is T) {
32+
}
33+
s = T();
34+
s.answer();
35+
}
36+
37+
main() {
38+
test1();
39+
test2();
40+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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 a type `T` is made a type of interest in `S`
12+
/// then it cannot be promoted in `E`.
13+
/// @author [email protected]
14+
15+
class S {}
16+
17+
class T extends S {
18+
int answer() => 42;
19+
}
20+
21+
22+
main() {
23+
S s = S();
24+
while ([s = T(), s.answer()] == []) {
25+
// ^^^^^^
26+
// [analyzer] unspecified
27+
// [cfe] unspecified
28+
if (s is T) {} // make `T` a type of interest
29+
}
30+
}
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 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 a type `T` is made a type of interest in `S`
12+
/// then it can be promoted in `after(N)`.
13+
/// @author [email protected]
14+
15+
class S {}
16+
17+
class T extends S {
18+
int answer() => 42;
19+
}
20+
21+
main() {
22+
S s = S();
23+
while (1 > 2) {
24+
if (s is T) {}
25+
}
26+
s = T();
27+
s.answer();
28+
}

0 commit comments

Comments
 (0)