Skip to content

Commit 66635c3

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Add language tests for "why not promoted" functionality.
These tests just cover the CFE functionality. Once #44905 is addressed, I'll add test expectations for the analyzer. Note: these tests uncovered two unreelated bugs: #45551 and #45552. Bug: #44897 Change-Id: I465b157afc2cc15bcc5ce083aaa74614313a38a6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193581 Commit-Queue: Paul Berry <[email protected]> Reviewed-by: Leaf Petersen <[email protected]> Reviewed-by: Bob Nystrom <[email protected]>
1 parent 904882f commit 66635c3

11 files changed

+1572
-0
lines changed

tests/language/why_not_promoted/argument_type_not_assignable_nullability_error_test.dart

Lines changed: 593 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright (c) 2021, 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+
abstract class C {
6+
C? operator +(int i);
7+
int get cProperty => 0;
8+
}
9+
10+
direct_assignment(int? i, int? j) {
11+
if (i == null) return;
12+
i = j;
13+
//^
14+
// [context 1] Variable 'i' could be null due to an intervening write.
15+
i.isEven;
16+
//^
17+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
18+
//^
19+
// [cfe 1] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
20+
}
21+
22+
compound_assignment(C? c, int i) {
23+
if (c == null) return;
24+
c += i;
25+
//^
26+
// [context 2] Variable 'c' could be null due to an intervening write.
27+
c.cProperty;
28+
//^
29+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
30+
//^
31+
// [cfe 2] Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
32+
}
33+
34+
via_postfix_op(C? c) {
35+
if (c == null) return;
36+
c++;
37+
//^
38+
// [context 3] Variable 'c' could be null due to an intervening write.
39+
c.cProperty;
40+
//^
41+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
42+
//^
43+
// [cfe 3] Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
44+
}
45+
46+
via_prefix_op(C? c) {
47+
if (c == null) return;
48+
++c;
49+
//^
50+
// [context 4] Variable 'c' could be null due to an intervening write.
51+
c.cProperty;
52+
//^
53+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
54+
//^
55+
// [cfe 4] Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
56+
}
57+
58+
via_for_each_statement(int? i, List<int?> list) {
59+
if (i == null) return;
60+
for (i in list) {
61+
// ^
62+
// [context 5] Variable 'i' could be null due to an intervening write.
63+
i.isEven;
64+
// ^
65+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
66+
//^
67+
// [cfe 5] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
68+
}
69+
}
70+
71+
via_for_each_list_element(int? i, List<int?> list) {
72+
if (i == null) return;
73+
[for (i in list) i.isEven];
74+
// ^
75+
// [context 6] Variable 'i' could be null due to an intervening write.
76+
// ^
77+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
78+
// ^
79+
// [cfe 6] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
80+
}
81+
82+
via_for_each_set_element(int? i, List<int?> list) {
83+
if (i == null) return;
84+
({for (i in list) i.isEven});
85+
// ^
86+
// [context 7] Variable 'i' could be null due to an intervening write.
87+
// ^
88+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
89+
// ^
90+
// [cfe 7] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
91+
}
92+
93+
via_for_each_map_key(int? i, List<int?> list) {
94+
if (i == null) return;
95+
({for (i in list) i.isEven: null});
96+
// ^
97+
// [context 8] Variable 'i' could be null due to an intervening write.
98+
// ^
99+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
100+
// ^
101+
// [cfe 8] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
102+
}
103+
104+
via_for_each_map_value(int? i, List<int?> list) {
105+
if (i == null) return;
106+
({for (i in list) null: i.isEven});
107+
// ^
108+
// [context 9] Variable 'i' could be null due to an intervening write.
109+
// ^
110+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
111+
// ^
112+
// [cfe 9] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
113+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright (c) 2021, 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+
class C {
6+
get_property_via_explicit_this() {
7+
if (this.i == null) return;
8+
this.i.isEven;
9+
// ^^^^^^
10+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
11+
// ^
12+
// [cfe 1] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
13+
}
14+
15+
get_property_via_explicit_this_parenthesized() {
16+
if ((this).i == null) return;
17+
(this).i.isEven;
18+
// ^^^^^^^^
19+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
20+
// ^
21+
// [cfe 2] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
22+
}
23+
24+
get_property_by_implicit_this() {
25+
if (i == null) return;
26+
i.isEven;
27+
// ^
28+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
29+
// ^
30+
// [cfe 3] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
31+
}
32+
}
33+
34+
extension E on C {
35+
int? get i => null;
36+
// ^
37+
// [context 1] 'i' refers to a property so it couldn't be promoted.
38+
// [context 2] 'i' refers to a property so it couldn't be promoted.
39+
// [context 3] 'i' refers to a property so it couldn't be promoted.
40+
// [context 4] 'i' refers to a property so it couldn't be promoted.
41+
// [context 5] 'i' refers to a property so it couldn't be promoted.
42+
int? get j => null;
43+
}
44+
45+
class D extends C {
46+
get_property_by_implicit_super() {
47+
if (i == null) return;
48+
i.isEven;
49+
// ^
50+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
51+
// ^
52+
// [cfe 4] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
53+
}
54+
}
55+
56+
get_property_via_prefixed_identifier(C c) {
57+
if (c.i == null) return;
58+
c.i.isEven;
59+
//^^^
60+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
61+
// ^
62+
// [cfe 5] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
63+
}
64+
65+
get_property_via_prefixed_identifier_mismatched_target(C c1, C c2) {
66+
// Note: no context on this error because the property the user is attempting
67+
// to promote is on c1, but the property the user is accessing is on c2.
68+
if (c1.i == null) return;
69+
c2.i.isEven;
70+
//^^^^
71+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
72+
// ^
73+
// [cfe] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
74+
}
75+
76+
get_property_via_prefixed_identifier_mismatched_property(C c) {
77+
// Note: no context on this error because the property the user is attempting
78+
// to promote is C.i, but the property the user is accessing is C.j.
79+
if (c.i == null) return;
80+
c.j.isEven;
81+
//^^^
82+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
83+
// ^
84+
// [cfe] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
85+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (c) 2021, 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+
class C {
6+
int? i;
7+
// ^
8+
// [context 1] 'i' refers to a property so it couldn't be promoted.
9+
// [context 2] 'i' refers to a property so it couldn't be promoted.
10+
// [context 3] 'i' refers to a property so it couldn't be promoted.
11+
// [context 4] 'i' refers to a property so it couldn't be promoted.
12+
// [context 5] 'i' refers to a property so it couldn't be promoted.
13+
// [context 6] 'i' refers to a property so it couldn't be promoted.
14+
int? j;
15+
16+
get_field_via_explicit_this() {
17+
if (this.i == null) return;
18+
this.i.isEven;
19+
// ^^^^^^
20+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
21+
// ^
22+
// [cfe 1] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
23+
}
24+
25+
get_field_via_explicit_this_parenthesized() {
26+
if ((this).i == null) return;
27+
(this).i.isEven;
28+
// ^^^^^^^^
29+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
30+
// ^
31+
// [cfe 2] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
32+
}
33+
34+
get_field_by_implicit_this() {
35+
if (i == null) return;
36+
i.isEven;
37+
// ^
38+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
39+
// ^
40+
// [cfe 3] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
41+
}
42+
}
43+
44+
class D extends C {
45+
get_field_via_explicit_super() {
46+
if (super.i == null) return;
47+
super.i.isEven;
48+
// ^^^^^^^
49+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
50+
// ^
51+
// [cfe 4] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
52+
}
53+
54+
get_field_by_implicit_super() {
55+
if (i == null) return;
56+
i.isEven;
57+
// ^
58+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
59+
// ^
60+
// [cfe 5] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
61+
}
62+
}
63+
64+
get_field_via_prefixed_identifier(C c) {
65+
if (c.i == null) return;
66+
c.i.isEven;
67+
//^^^
68+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
69+
// ^
70+
// [cfe 6] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
71+
}
72+
73+
get_field_via_prefixed_identifier_mismatched_target(C c1, C c2) {
74+
// Note: no context on this error because the property the user is attempting
75+
// to promote is on c1, but the property the user is accessing is on c2.
76+
if (c1.i == null) return;
77+
c2.i.isEven;
78+
//^^^^
79+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
80+
// ^
81+
// [cfe] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
82+
}
83+
84+
get_field_via_prefixed_identifier_mismatched_property(C c) {
85+
// Note: no context on this error because the property the user is attempting
86+
// to promote is C.i, but the property the user is accessing is C.j.
87+
if (c.i == null) return;
88+
c.j.isEven;
89+
//^^^
90+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
91+
// ^
92+
// [cfe] Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
93+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (c) 2021, 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+
// This test contains a test case for each condition that can lead to the front
6+
// end's `ForInLoopTypeNotIterableNullability` or
7+
// `ForInLoopTypeNotIterablePartNullability` errors, for which we wish to report
8+
// "why not promoted" context information.
9+
10+
class C1 {
11+
List<int>? bad;
12+
// ^
13+
// [context 1] 'bad' refers to a property so it couldn't be promoted.
14+
// [context 2] 'bad' refers to a property so it couldn't be promoted.
15+
// [context 3] 'bad' refers to a property so it couldn't be promoted.
16+
// [context 4] 'bad' refers to a property so it couldn't be promoted.
17+
// [context 5] 'bad' refers to a property so it couldn't be promoted.
18+
// [context 6] 'bad' refers to a property so it couldn't be promoted.
19+
// [context 7] 'bad' refers to a property so it couldn't be promoted.
20+
// [context 8] 'bad' refers to a property so it couldn't be promoted.
21+
}
22+
23+
forStatement(C1 c) {
24+
if (c.bad == null) return;
25+
for (var x in c.bad) {}
26+
// ^^^^^
27+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
28+
// ^
29+
// [cfe 1] The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
30+
}
31+
32+
forElementInList(C1 c) {
33+
if (c.bad == null) return;
34+
[for (var x in c.bad) null];
35+
// ^^^^^
36+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
37+
// ^
38+
// [cfe 2] The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
39+
}
40+
41+
forElementInSet(C1 c) {
42+
if (c.bad == null) return;
43+
<dynamic>{for (var x in c.bad) null};
44+
// ^^^^^
45+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
46+
// ^
47+
// [cfe 3] The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
48+
}
49+
50+
forElementInMap(C1 c) {
51+
if (c.bad == null) return;
52+
<dynamic, dynamic>{for (var x in c.bad) null: null};
53+
// ^^^^^
54+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
55+
// ^
56+
// [cfe 4] The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
57+
}
58+
59+
forElementInAmbiguousSet_resolvableDuringParsing(C1 c) {
60+
if (c.bad == null) return;
61+
({for (var x in c.bad) null});
62+
// ^^^^^
63+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
64+
// ^
65+
// [cfe 5] The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
66+
}
67+
68+
forElementInAmbiguousMap_resolvableDuringParsing(C1 c) {
69+
if (c.bad == null) return;
70+
({for (var x in c.bad) null: null});
71+
// ^^^^^
72+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
73+
// ^
74+
// [cfe 6] The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
75+
}
76+
77+
forElementInAmbiguousSet_notResolvableDuringParsing(C1 c, List list) {
78+
if (c.bad == null) return;
79+
({for (var x in c.bad) ...list});
80+
// ^^^^^
81+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
82+
// ^
83+
// [cfe 7] The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
84+
}
85+
86+
forElementInAmbiguousMap_notResolvableDuringParsing(C1 c, Map map) {
87+
if (c.bad == null) return;
88+
({for (var x in c.bad) ...map});
89+
// ^^^^^
90+
// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
91+
// ^
92+
// [cfe 8] The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
93+
}

0 commit comments

Comments
 (0)