Skip to content

Commit 432cf3f

Browse files
authored
#3057. Add tests for method invocation (#3083)
* #3057. Add tests for method invocation * Minor code improvement * Minor code-style changes * Add async function case * Apply review suggestions * Apply review suggestions, iteration #2.
1 parent d23ae2c commit 432cf3f

7 files changed

+362
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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 - Method invocation: If `N` is an expression of the form
6+
/// `E1.m1(E2)`, then:
7+
/// - Let `before(E1) = before(N)`
8+
/// - Let `before(E2) = after(E1)`
9+
/// - Let `T` be the static return type of the invocation
10+
/// - If `T <: Never` then:
11+
/// - Let `after(N) = unreachable(after(E2))`.
12+
/// - Otherwise:
13+
/// - Let `after(N) = after(E2)`.
14+
///
15+
/// @description Checks that for an expression of the form `E1.m1(E2)`
16+
/// `before(E2) = after(E1)`. Test that if `after(E1)` is unreachable then
17+
/// `before(E2)` is also unreachable.
18+
/// @author [email protected]
19+
20+
void test<T extends Never>(T n) {
21+
late int i;
22+
if (2 > 1) {
23+
n.foo(i = 42);
24+
}
25+
i; // Definitely unassigned
26+
//^
27+
// [analyzer] unspecified
28+
// [cfe] unspecified
29+
}
30+
31+
main() {
32+
print(test);
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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 - Method invocation: If `N` is an expression of the form
6+
/// `E1.m1(E2)`, then:
7+
/// - Let `before(E1) = before(N)`
8+
/// - Let `before(E2) = after(E1)`
9+
/// - Let `T` be the static return type of the invocation
10+
/// - If `T <: Never` then:
11+
/// - Let `after(N) = unreachable(after(E2))`.
12+
/// - Otherwise:
13+
/// - Let `after(N) = after(E2)`.
14+
///
15+
/// @description Checks that for an expression of the form `E1.m1(E2)`
16+
/// `before(E2) = after(E1)`. Test that if `after(E1)` is unreachable then
17+
/// `before(E2)` is also unreachable.
18+
/// @author [email protected]
19+
20+
class C {
21+
C(int i);
22+
void foo(int j) {}
23+
}
24+
25+
void test<T extends Never>(T n) {
26+
late int i;
27+
if (2 > 1) {
28+
C(n).foo(i = 42);
29+
}
30+
i; // Definitely unassigned
31+
//^
32+
// [analyzer] unspecified
33+
// [cfe] unspecified
34+
}
35+
36+
main() {
37+
print(test);
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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 - Method invocation: If `N` is an expression of the form
6+
/// `E1.m1(E2)`, then:
7+
/// - Let `before(E1) = before(N)`
8+
/// - Let `before(E2) = after(E1)`
9+
/// - Let `T` be the static return type of the invocation
10+
/// - If `T <: Never` then:
11+
/// - Let `after(N) = unreachable(after(E2))`.
12+
/// - Otherwise:
13+
/// - Let `after(N) = after(E2)`.
14+
///
15+
/// @description Checks that if the static type of the expression of the form
16+
/// `E1.m1(E2)` is `Never` `after(N) = unreachable(after(E2))`.
17+
/// @author [email protected]
18+
19+
class C<T extends Never> {
20+
T foo() => throw "";
21+
Future<T> bar() async {
22+
throw "";
23+
}
24+
}
25+
26+
void test1() {
27+
late int i;
28+
if (2 > 1) {
29+
C().foo();
30+
i = 42;
31+
}
32+
i; // Definitely unassigned
33+
//^
34+
// [analyzer] unspecified
35+
// [cfe] unspecified
36+
}
37+
38+
void test2() {
39+
late int i;
40+
if (2 > 1) {
41+
C().bar(); // Return type is not `Never`
42+
i = 42;
43+
}
44+
i; // Not definitely unassigned
45+
}
46+
47+
void test3() async {
48+
late int i;
49+
if (2 > 1) {
50+
await C().bar();
51+
i = 42;
52+
}
53+
i; // Definitely unassigned
54+
//^
55+
// [analyzer] unspecified
56+
// [cfe] unspecified
57+
}
58+
59+
main() {
60+
print(test1);
61+
print(test2);
62+
print(test3);
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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 - Method invocation: If `N` is an expression of the form
6+
/// `E1.m1(E2)`, then:
7+
/// - Let `before(E1) = before(N)`
8+
/// - Let `before(E2) = after(E1)`
9+
/// - Let `T` be the static return type of the invocation
10+
/// - If `T <: Never` then:
11+
/// - Let `after(N) = unreachable(after(E2))`.
12+
/// - Otherwise:
13+
/// - Let `after(N) = after(E2)`.
14+
///
15+
/// @description Checks that if the static type of the expression of the form
16+
/// `E1.m1(E2)` is `Never` then `E2` is still reachable.
17+
/// @author [email protected]
18+
19+
class C<T extends Never> {
20+
T foo(int x) => throw "foo";
21+
T bar([int x = 0]) => throw "bar";
22+
T baz({int x = 0}) => throw "baz";
23+
T qux({required int x}) => throw "qux";
24+
}
25+
26+
void test1() {
27+
late int i;
28+
try {
29+
C().foo(i = 42);
30+
} catch (_) {}
31+
i; // Not definitely unassigned
32+
}
33+
34+
void test2() {
35+
late int i;
36+
try {
37+
C().bar(i = 42);
38+
} catch (_) {}
39+
i;
40+
}
41+
42+
void test3() {
43+
late int i;
44+
try {
45+
C().baz(x: i = 42);
46+
} catch (_) {}
47+
i;
48+
}
49+
50+
void test4() {
51+
late int i;
52+
try {
53+
C().qux(x: i = 42);
54+
} catch (_) {}
55+
i;
56+
}
57+
58+
main() {
59+
test1();
60+
test2();
61+
test3();
62+
test4();
63+
}
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 - Method invocation: If `N` is an expression of the form
6+
/// `E1.m1(E2)`, then:
7+
/// - Let `before(E1) = before(N)`
8+
/// - Let `before(E2) = after(E1)`
9+
/// - Let `T` be the static return type of the invocation
10+
/// - If `T <: Never` then:
11+
/// - Let `after(N) = unreachable(after(E2))`.
12+
/// - Otherwise:
13+
/// - Let `after(N) = after(E2)`.
14+
///
15+
/// @description Checks that for an expression of the form `E1.m1(E2)`, if the
16+
/// static type of `E1` is not `Never` then `after(N) = after(E2)`. This is
17+
/// tested by detecting that `i = 42` is considered to be guaranteed to have
18+
/// been executed when `i;` is executed.
19+
/// @author [email protected]
20+
21+
class C {
22+
void foo(int x) {}
23+
void bar([int x = 0]) {}
24+
void baz({int x = 0}) {}
25+
void qux({required int x}) {}
26+
}
27+
28+
void test1() {
29+
int i;
30+
C().foo(i = 42);
31+
i; // Definitely assigned
32+
}
33+
34+
void test2() {
35+
int i;
36+
C().bar(i = 42);
37+
i; // Definitely assigned
38+
}
39+
40+
void test3() {
41+
int i;
42+
C().baz(x: i = 42);
43+
i; // Definitely assigned
44+
}
45+
46+
void test4() {
47+
int i;
48+
C().qux(x: i = 42);
49+
i; // Definitely assigned
50+
}
51+
52+
main() {
53+
test1();
54+
test2();
55+
test3();
56+
test4();
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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 - Method invocation: If `N` is an expression of the form
6+
/// `E1.m1(E2)`, then:
7+
/// - Let `before(E1) = before(N)`
8+
/// - Let `before(E2) = after(E1)`
9+
/// - Let `T` be the static return type of the invocation
10+
/// - If `T <: Never` then:
11+
/// - Let `after(N) = unreachable(after(E2))`.
12+
/// - Otherwise:
13+
/// - Let `after(N) = after(E2)`.
14+
///
15+
/// @description Checks that for an expression of the form `E1.m1(E2)`, if the
16+
/// static type of `E1` is not `Never` then `after(N) = after(E2)`. This is
17+
/// tested by detecting that `i = 42` is considered to be guaranteed to have
18+
/// been executed when `i;` is executed. Test the case when `m1` is a getter
19+
/// returning a function type.
20+
/// @author [email protected]
21+
22+
class C {
23+
void Function(int) get foo => (int x) {};
24+
void Function([int]) get bar => ([int x = 0]) {};
25+
void Function({int x}) get baz => ({int x = 0}) {};
26+
void Function({required int x}) get qux => ({required int x}) {};
27+
}
28+
29+
void test1() {
30+
int i;
31+
C().foo(i = 42);
32+
i; // Definitely assigned
33+
}
34+
35+
void test2() {
36+
int i;
37+
C().bar(i = 42);
38+
i; // Definitely assigned
39+
}
40+
41+
void test3() {
42+
int i;
43+
C().baz(x: i = 42);
44+
i; // Definitely assigned
45+
}
46+
47+
void test4() {
48+
int i;
49+
C().qux(x: i = 42);
50+
i; // Definitely assigned
51+
}
52+
53+
main() {
54+
test1();
55+
test2();
56+
test3();
57+
test4();
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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 - Method invocation: If `N` is an expression of the form
6+
/// `E1.m1(E2)`, then:
7+
/// - Let `before(E1) = before(N)`
8+
/// - Let `before(E2) = after(E1)`
9+
/// - Let `T` be the static return type of the invocation
10+
/// - If `T <: Never` then:
11+
/// - Let `after(N) = unreachable(after(E2))`.
12+
/// - Otherwise:
13+
/// - Let `after(N) = after(E2)`.
14+
///
15+
/// @description Checks that for an expression of the form `E1.m1(E2)`
16+
/// `before(E2) = after(E1)`. Test that if `m1` is a getter returning type
17+
/// `Never` then `before(E2)` is unreachable.
18+
/// @author [email protected]
19+
20+
class C<T extends Never> {
21+
Never get foo => throw "Never";
22+
T get bar => throw "Never";
23+
}
24+
25+
void test1() {
26+
late int i;
27+
if (2 > 1) {
28+
C().foo(i = 42); // ignore: receiver_of_type_never
29+
}
30+
i; // Definitely unassigned
31+
//^
32+
// [analyzer] unspecified
33+
// [cfe] unspecified
34+
}
35+
36+
void test2() {
37+
late int i;
38+
if (2 > 1) {
39+
C().bar(i = 42); // ignore: receiver_of_type_never
40+
}
41+
i; // Definitely unassigned
42+
//^
43+
// [analyzer] unspecified
44+
// [cfe] unspecified
45+
}
46+
47+
main() {
48+
print(test1);
49+
print(test2);
50+
}

0 commit comments

Comments
 (0)