Skip to content

Commit eb144d3

Browse files
authored
#3057. Add flow analysis tests for the for-in statement (#3115)
Add flow analysis tests for the `for-in` statement
1 parent d0054f6 commit eb144d3

22 files changed

+943
-13
lines changed

TypeSystem/flow-analysis/definite_assignment_A04_t01.dart

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
/// @assertion assigned is a boolean value indicating whether the variable has
6-
/// definitely been assigned at the given point in the source code. When assigned
7-
/// is true, we say that the variable is definitely assigned at that point.
5+
/// @assertion `assigned` is a boolean value indicating whether the variable has
6+
/// definitely been assigned at the given point in the source code. When
7+
/// `assigned` is true, we say that the variable is definitely assigned at that
8+
/// point.
89
///
9-
/// @description Checks definite assignment and for-in loop
10+
/// @description Checks that an assignment in the body of a `for-in` loop is
11+
/// detected by flow analysis.
1012
/// @author [email protected]
1113
1214
main() {
1315
var collection = [3, 1, 4, 1, 5];
14-
int n;
16+
late int n;
1517
for (var v in collection) {
1618
n = 42;
1719
}
18-
n; // It's an error to read local non-nullable variable when it is not definitely assigned
19-
//^
20-
// [analyzer] unspecified
21-
// [cfe] unspecified
20+
n; // Not definitely unassigned
2221
}

TypeSystem/flow-analysis/definite_assignment_A04_t02.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
/// @assertion assigned is a boolean value indicating whether the variable has
6-
/// definitely been assigned at the given point in the source code. When assigned
7-
/// is true, we say that the variable is definitely assigned at that point.
5+
/// @assertion `assigned` is a boolean value indicating whether the variable has
6+
/// definitely been assigned at the given point in the source code. When
7+
/// `assigned` is true, we say that the variable is definitely assigned at that
8+
/// point.
89
///
9-
/// @description Checks definite assignment and for-in loop
10+
/// @description Checks that an assignment in a `for-in` collection part is
11+
/// treated by the flow analysis as a definite assignment.
1012
/// @author [email protected]
1113
1214
main() {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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 if `E` has type `Never` then an assignment in `X`
12+
/// is unreachable.
13+
/// @author [email protected]
14+
15+
Never foo() => throw "Never";
16+
17+
test1() {
18+
late int i;
19+
if (2 > 1) {
20+
for (i in foo()) {}
21+
}
22+
i; // Definitely unassigned.
23+
//^
24+
// [analyzer] unspecified
25+
// [cfe] unspecified
26+
}
27+
28+
test2(Never n) {
29+
late int i;
30+
if (2 > 1) {
31+
for (i in n) {}
32+
}
33+
i; // Definitely unassigned.
34+
//^
35+
// [analyzer] unspecified
36+
// [cfe] unspecified
37+
}
38+
39+
test3<T extends Never>(T n) {
40+
late int i;
41+
if (2 > 1) {
42+
for (i in n) {}
43+
}
44+
i; // Definitely unassigned.
45+
//^
46+
// [analyzer] unspecified
47+
// [cfe] unspecified
48+
}
49+
50+
main() {
51+
print(test1);
52+
print(test2);
53+
print(test3);
54+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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 if `E` has type `Never` then an assignment in `S`
12+
/// is unreachable.
13+
/// @author [email protected]
14+
15+
Never foo() => throw "Never";
16+
17+
test1() {
18+
late int i;
19+
if (2 > 1) {
20+
for (var j in foo()) {
21+
i = 42;
22+
}
23+
}
24+
i; // Definitely unassigned.
25+
//^
26+
// [analyzer] unspecified
27+
// [cfe] unspecified
28+
}
29+
30+
test2(Never n) {
31+
late int i;
32+
if (2 > 1) {
33+
for (var j in n) {
34+
i = 42;
35+
}
36+
}
37+
i; // Definitely unassigned.
38+
//^
39+
// [analyzer] unspecified
40+
// [cfe] unspecified
41+
}
42+
43+
test3<T extends Never>(T n) {
44+
late int i;
45+
if (2 > 1) {
46+
for (var j in n) {
47+
i = 42;
48+
}
49+
}
50+
i; // Definitely unassigned.
51+
//^
52+
// [analyzer] unspecified
53+
// [cfe] unspecified
54+
}
55+
56+
main() {
57+
print(test1);
58+
print(test2);
59+
print(test3);
60+
}
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 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 if `E` has type `Never` then an assignment after
12+
/// `N` is unreachable.
13+
/// @author [email protected]
14+
15+
Never foo() => throw "Never";
16+
17+
test1() {
18+
late int i;
19+
if (2 > 1) {
20+
for (var j in foo()) {}
21+
i = 42;
22+
}
23+
i; // Definitely unassigned.
24+
//^
25+
// [analyzer] unspecified
26+
// [cfe] unspecified
27+
}
28+
29+
test2(Never n) {
30+
late int i;
31+
if (2 > 1) {
32+
for (var j in n) {}
33+
i = 42;
34+
}
35+
i; // Definitely unassigned.
36+
//^
37+
// [analyzer] unspecified
38+
// [cfe] unspecified
39+
}
40+
41+
test3<T extends Never>(T n) {
42+
late int i;
43+
if (2 > 1) {
44+
for (var j in n) {}
45+
i = 42;
46+
}
47+
i; // Definitely unassigned.
48+
//^
49+
// [analyzer] unspecified
50+
// [cfe] unspecified
51+
}
52+
53+
main() {
54+
print(test1);
55+
print(test2);
56+
print(test3);
57+
}
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 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 if elements of `E` has type `Never` then an
12+
/// assignment in `X` is unreachable.
13+
/// @author [email protected]
14+
/// @issue 60393
15+
16+
Never foo() => throw "Never";
17+
18+
test1() {
19+
late int i;
20+
if (2 > 1) {
21+
for (i in [foo()]) {}
22+
}
23+
i; // Definitely unassigned.
24+
//^
25+
// [analyzer] unspecified
26+
// [cfe] unspecified
27+
}
28+
29+
test2(Never n) {
30+
late int i;
31+
if (2 > 1) {
32+
for (i in [n]) {}
33+
}
34+
i; // Definitely unassigned.
35+
//^
36+
// [analyzer] unspecified
37+
// [cfe] unspecified
38+
}
39+
40+
test3<T extends Never>(T n) {
41+
late int i;
42+
if (2 > 1) {
43+
for (i in [n]) {}
44+
}
45+
i; // Definitely unassigned.
46+
//^
47+
// [analyzer] unspecified
48+
// [cfe] unspecified
49+
}
50+
51+
test4() {
52+
late int i;
53+
if (2 > 1) {
54+
for (i in <Never>[]) {}
55+
}
56+
i; // Definitely unassigned.
57+
//^
58+
// [analyzer] unspecified
59+
// [cfe] unspecified
60+
}
61+
62+
main() {
63+
print(test1);
64+
print(test2);
65+
print(test3);
66+
print(test4);
67+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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 if elements of `E` has type `Never` then an
12+
/// assignment in `S` is unreachable.
13+
/// @author [email protected]
14+
/// @issue 60393
15+
16+
Never foo() => throw "Never";
17+
18+
test1() {
19+
late int i;
20+
if (2 > 1) {
21+
for (var j in [foo()]) {
22+
i = 42;
23+
}
24+
}
25+
i; // Definitely unassigned.
26+
//^
27+
// [analyzer] unspecified
28+
// [cfe] unspecified
29+
}
30+
31+
test2(Never n) {
32+
late int i;
33+
if (2 > 1) {
34+
for (var j in [n]) {
35+
i = 42;
36+
}
37+
}
38+
i; // Definitely unassigned.
39+
//^
40+
// [analyzer] unspecified
41+
// [cfe] unspecified
42+
}
43+
44+
test3<T extends Never>(T n) {
45+
late int i;
46+
if (2 > 1) {
47+
for (var j in [n]) {
48+
i = 42;
49+
}
50+
}
51+
i; // Definitely unassigned.
52+
//^
53+
// [analyzer] unspecified
54+
// [cfe] unspecified
55+
}
56+
57+
test4() {
58+
late int i;
59+
if (2 > 1) {
60+
for (var j in <Never>[]) {
61+
i = 42;
62+
}
63+
}
64+
i; // Definitely unassigned.
65+
//^
66+
// [analyzer] unspecified
67+
// [cfe] unspecified
68+
}
69+
70+
main() {
71+
print(test1);
72+
print(test2);
73+
print(test3);
74+
print(test4);
75+
}

0 commit comments

Comments
 (0)