Skip to content

Commit 6627f8c

Browse files
authored
#3057. Add flow analysis try-finally tests (#3139)
Add flow analysis try-finally tests
1 parent fed9861 commit 6627f8c

13 files changed

+914
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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 try finally: If `N` is a try/finally statement of the form
6+
/// `try B1 finally B2` then:
7+
/// - Let `before(B1) = split(before(N))`
8+
/// - Let `before(B2) = split(join(drop(after(B1)),
9+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`
10+
/// - Let `after(N) = restrict(after(B1), after(B2), assignedIn(B2))`
11+
///
12+
/// @description Checks that `before(B1) = split(before(N))`. Test that if a
13+
/// variable is assigned in `B2` only then it is definitely unassigned in `B1`
14+
/// @author [email protected]
15+
16+
main() {
17+
late int i;
18+
try {
19+
i; // Definitely unassigned
20+
// ^
21+
// [analyzer] unspecified
22+
// [cfe] unspecified
23+
} finally {
24+
i = 42;
25+
}
26+
}
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 try finally: If `N` is a try/finally statement of the form
6+
/// `try B1 finally B2` then:
7+
/// - Let `before(B1) = split(before(N))`
8+
/// - Let `before(B2) = split(join(drop(after(B1)),
9+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`
10+
/// - Let `after(N) = restrict(after(B1), after(B2), assignedIn(B2))`
11+
///
12+
/// @description Checks that `before(B2) = split(join(drop(after(B1)),
13+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`. Test that if
14+
/// some variable is assigned in `B1` then it is "possibly assigned" in `B2`.
15+
/// @author [email protected]
16+
17+
class C {
18+
int v;
19+
C(this.v);
20+
}
21+
22+
Never foo() => throw "Never";
23+
24+
test1() {
25+
late int i;
26+
try {
27+
foo();
28+
i = 42;
29+
} finally {
30+
i; // Possibly assigned
31+
}
32+
}
33+
34+
test2(Never n) {
35+
late int i;
36+
try {
37+
n;
38+
(i,) = (42,);
39+
} finally {
40+
i;
41+
}
42+
}
43+
44+
test3<T extends Never>(T n) {
45+
late int i;
46+
try {
47+
n;
48+
(x: i) = (x: 42);
49+
} finally {
50+
i;
51+
}
52+
}
53+
54+
test4() {
55+
late int i;
56+
try {
57+
foo();
58+
C(v: i) = C(42);
59+
} finally {
60+
i;
61+
}
62+
}
63+
64+
main() {
65+
print(test1);
66+
print(test2);
67+
print(test3);
68+
print(test4);
69+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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 try finally: If `N` is a try/finally statement of the form
6+
/// `try B1 finally B2` then:
7+
/// - Let `before(B1) = split(before(N))`
8+
/// - Let `before(B2) = split(join(drop(after(B1)),
9+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`
10+
/// - Let `after(N) = restrict(after(B1), after(B2), assignedIn(B2))`
11+
///
12+
/// @description Checks that `before(B2) = split(join(drop(after(B1)),
13+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`. Test that if
14+
/// some variable is assigned in `B1` then it is "possibly assigned" in `B2`.
15+
/// @author [email protected]
16+
17+
class C {
18+
int v;
19+
C(this.v);
20+
}
21+
22+
test1() {
23+
late int i;
24+
try {
25+
if (false) {
26+
i = 42;
27+
}
28+
} finally {
29+
i; // Possibly assigned
30+
}
31+
}
32+
33+
test2() {
34+
late int i;
35+
try {
36+
if (false) {
37+
(i, ) = (42, );
38+
}
39+
} finally {
40+
i;
41+
}
42+
}
43+
44+
test3() {
45+
late int i;
46+
try {
47+
if (false) {
48+
(x: i) = (x: 42);
49+
}
50+
} finally {
51+
i;
52+
}
53+
}
54+
55+
test4() {
56+
late int i;
57+
try {
58+
if (false) {
59+
C(v: i) = C(42);
60+
}
61+
} finally {
62+
i;
63+
}
64+
}
65+
66+
main() {
67+
print(test1);
68+
print(test2);
69+
print(test3);
70+
print(test4);
71+
}
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 try finally: If `N` is a try/finally statement of the form
6+
/// `try B1 finally B2` then:
7+
/// - Let `before(B1) = split(before(N))`
8+
/// - Let `before(B2) = split(join(drop(after(B1)),
9+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`
10+
/// - Let `after(N) = restrict(after(B1), after(B2), assignedIn(B2))`
11+
///
12+
/// @description Checks that `before(B2) = split(join(drop(after(B1)),
13+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`. Test that if
14+
/// some variable is assigned in `B1` then it is "possibly assigned" in `B2`.
15+
/// @author [email protected]
16+
17+
class C {
18+
int v;
19+
C(this.v);
20+
}
21+
22+
test1() {
23+
int i;
24+
try {
25+
i = 42;
26+
} finally {
27+
i; // Possibly assigned
28+
// ^
29+
// [analyzer] unspecified
30+
// [cfe] unspecified
31+
}
32+
}
33+
34+
test2() {
35+
int i;
36+
try {
37+
(i,) = (42,);
38+
} finally {
39+
i;
40+
// ^
41+
// [analyzer] unspecified
42+
// [cfe] unspecified
43+
}
44+
}
45+
46+
test3() {
47+
int i;
48+
try {
49+
(x: i) = (x: 42);
50+
} finally {
51+
i;
52+
// ^
53+
// [analyzer] unspecified
54+
// [cfe] unspecified
55+
}
56+
}
57+
58+
test4() {
59+
int i;
60+
try {
61+
C(v: i) = C(42);
62+
} finally {
63+
i;
64+
// ^
65+
// [analyzer] unspecified
66+
// [cfe] unspecified
67+
}
68+
}
69+
70+
main() {
71+
print(test1);
72+
print(test2);
73+
print(test3);
74+
print(test4);
75+
}
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 try finally: If `N` is a try/finally statement of the form
6+
/// `try B1 finally B2` then:
7+
/// - Let `before(B1) = split(before(N))`
8+
/// - Let `before(B2) = split(join(drop(after(B1)),
9+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`
10+
/// - Let `after(N) = restrict(after(B1), after(B2), assignedIn(B2))`
11+
///
12+
/// @description Checks that `before(B2) = split(join(drop(after(B1)),
13+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`. Test that if
14+
/// some promoted variable is captured in `B1` then it is demoted in `B2`.
15+
/// @author [email protected]
16+
17+
class C {
18+
int v;
19+
C(this.v);
20+
}
21+
22+
test1(int? n) {
23+
if (n != null) { // `n` promoted to `int`
24+
try {
25+
() {n = 42;}; // `n` demoted to `int?`
26+
} finally {
27+
n.isEven;
28+
// ^^^^^^
29+
// [analyzer] unspecified
30+
// [cfe] unspecified
31+
}
32+
}
33+
}
34+
35+
test2(int? n) {
36+
if (n != null) {
37+
try {
38+
() {(n,) = (42,);};
39+
} finally {
40+
n.isEven;
41+
// ^^^^^^
42+
// [analyzer] unspecified
43+
// [cfe] unspecified
44+
}
45+
}
46+
}
47+
48+
test3(int? n) {
49+
if (n != null) {
50+
try {
51+
() {(x: n) = (x: 42);};
52+
} finally {
53+
n.isEven;
54+
// ^^^^^^
55+
// [analyzer] unspecified
56+
// [cfe] unspecified
57+
}
58+
}
59+
}
60+
61+
test4(int? n) {
62+
if (n != null) {
63+
try {
64+
() {C(v: n) = C(42);};
65+
} finally {
66+
n.isEven;
67+
// ^^^^^^
68+
// [analyzer] unspecified
69+
// [cfe] unspecified
70+
}
71+
}
72+
}
73+
74+
main() {
75+
print(test1);
76+
print(test2);
77+
print(test3);
78+
print(test4);
79+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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 try finally: If `N` is a try/finally statement of the form
6+
/// `try B1 finally B2` then:
7+
/// - Let `before(B1) = split(before(N))`
8+
/// - Let `before(B2) = split(join(drop(after(B1)),
9+
/// conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))))`
10+
/// - Let `after(N) = restrict(after(B1), after(B2), assignedIn(B2))`
11+
///
12+
/// @description Checks that
13+
/// `after(N) = restrict(after(B1), after(B2), assignedIn(B2))`. Test that if
14+
/// some variable is assigned in `B1` and `B1` throws then it is definitely
15+
/// assigned in dead code `after(N)`.
16+
/// @author [email protected]
17+
/// @issue 60503
18+
19+
class C {
20+
int v;
21+
C(this.v);
22+
}
23+
24+
Never foo() => throw "Never";
25+
26+
test1() {
27+
int i;
28+
try {
29+
foo();
30+
i = 42;
31+
} finally {
32+
}
33+
i; // Definitely assigned and in dead code
34+
}
35+
36+
test2(Never n) {
37+
int i;
38+
try {
39+
(i,) = (42,);
40+
n;
41+
} finally {
42+
}
43+
i;
44+
}
45+
46+
test3<T extends Never>(T n) {
47+
int i;
48+
try {
49+
n;
50+
(x: i) = (x: 42);
51+
} finally {
52+
}
53+
i;
54+
}
55+
56+
test4() {
57+
int i;
58+
try {
59+
C(v: i) = C(42);
60+
foo();
61+
} finally {
62+
}
63+
i;
64+
}
65+
66+
main() {
67+
print(test1);
68+
print(test2);
69+
print(test3);
70+
print(test4);
71+
}

0 commit comments

Comments
 (0)