Skip to content

Commit d2b3132

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Flow analysis: Pin down initialization behaviors before fixing #1785.
dart-lang/language#1785 has a wide enough impact that its fix will have to be bundled in with a language version (i.e. future versions of Dart will have to reproduce the old buggy behavior for code that's not opted in to the latest language version). Therefore, we'll have to maintain tests of the behavior both before and after the fix. This CL is the first step in that process, adding tests that validate the current (buggy) behavior. Bug: dart-lang/language#1785 Change-Id: I78f17999ac1cbc096a312ef977db24654e06a263 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210400 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent cf46f28 commit d2b3132

File tree

3 files changed

+291
-0
lines changed

3 files changed

+291
-0
lines changed

pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/local_boolean.dart

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ finalLocalBool(int? x) {
1111
}
1212
}
1313

14+
finalLocalBool_untyped(int? x) {
15+
final b = x == null;
16+
if (!b) {
17+
// No promotion due to https://github.com/dart-lang/language/issues/1785
18+
x;
19+
} else {
20+
x;
21+
}
22+
}
23+
1424
localBool(int? x) {
1525
bool b = x == null;
1626
if (!b) {
@@ -20,6 +30,16 @@ localBool(int? x) {
2030
}
2131
}
2232

33+
localBool_untyped(int? x) {
34+
var b = x == null;
35+
if (!b) {
36+
// No promotion due to https://github.com/dart-lang/language/issues/1785
37+
x;
38+
} else {
39+
x;
40+
}
41+
}
42+
2343
localBool_assigned(int? x, bool b1) {
2444
bool b2 = b1;
2545
b2 = x == null;
@@ -30,6 +50,16 @@ localBool_assigned(int? x, bool b1) {
3050
}
3151
}
3252

53+
localBool_assigned_untyped(int? x, bool b1) {
54+
var b2 = b1;
55+
b2 = x == null;
56+
if (!b2) {
57+
/*nonNullable*/ x;
58+
} else {
59+
x;
60+
}
61+
}
62+
3363
localBool_assignedDynamic(int? x, bool b1) {
3464
dynamic b2 = b1;
3565
b2 = x == null;
@@ -49,6 +79,15 @@ parameter_assigned(int? x, bool b) {
4979
}
5080
}
5181

82+
parameter_assigned_untyped(int? x, b) {
83+
b = x == null;
84+
if (!b) {
85+
/*nonNullable*/ x;
86+
} else {
87+
x;
88+
}
89+
}
90+
5291
parameter_assignedDynamic(int? x, dynamic b) {
5392
b = x == null;
5493
if (!b) {
@@ -69,6 +108,17 @@ lateFinalLocalBool(int? x) {
69108
}
70109
}
71110

111+
lateFinalLocalBool_untyped(int? x) {
112+
late final b = x == null;
113+
if (!b) {
114+
// We don't promote based on the initializers of late locals because we
115+
// don't know when they execute.
116+
x;
117+
} else {
118+
x;
119+
}
120+
}
121+
72122
lateLocalBool(int? x) {
73123
late bool b = x == null;
74124
if (!b) {
@@ -80,6 +130,17 @@ lateLocalBool(int? x) {
80130
}
81131
}
82132

133+
lateLocalBool_untyped(int? x) {
134+
late var b = x == null;
135+
if (!b) {
136+
// We don't promote based on the initializers of late locals because we
137+
// don't know when they execute.
138+
x;
139+
} else {
140+
x;
141+
}
142+
}
143+
83144
lateLocalBool_assignedAndInitialized(int? x, bool b1) {
84145
late bool b2 = b1;
85146
b2 = x == null;
@@ -90,6 +151,16 @@ lateLocalBool_assignedAndInitialized(int? x, bool b1) {
90151
}
91152
}
92153

154+
lateLocalBool_assignedAndInitialized_untyped(int? x, bool b1) {
155+
late var b2 = b1;
156+
b2 = x == null;
157+
if (!b2) {
158+
/*nonNullable*/ x;
159+
} else {
160+
x;
161+
}
162+
}
163+
93164
lateLocalBool_assignedButNotInitialized(int? x) {
94165
late bool b;
95166
b = x == null;
@@ -100,6 +171,16 @@ lateLocalBool_assignedButNotInitialized(int? x) {
100171
}
101172
}
102173

174+
lateLocalBool_assignedButNotInitialized_untyped(int? x) {
175+
late var b;
176+
b = x == null;
177+
if (!b) {
178+
/*nonNullable*/ x;
179+
} else {
180+
x;
181+
}
182+
}
183+
103184
rebaseWithDemotion(int? x, int? y, int? z, int? a) {
104185
x;
105186
y;

pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ localVariable() {
1313
x;
1414
}
1515

16+
localVariable_null() {
17+
var x = null;
18+
x;
19+
}
20+
1621
localVariable_hasInitializer(num a) {
1722
var x = a;
1823
x = 1;
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
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+
// @dart=2.13
6+
7+
import '../../static_type_helper.dart';
8+
9+
// This test checks whether a local boolean variable can be used to perform type
10+
// promotion, if that variable is implicitly typed.
11+
//
12+
// Due to https://github.com/dart-lang/language/issues/1785, initializer
13+
// expressions on implicitly typed variables are ignored for the purposes of
14+
// type promotion (however, later assignments to those variables still do
15+
// influence promotion). To avoid introducing breaking language changes, we
16+
// intend to preserve this behavior until a specific Dart language version.
17+
// This test verifies that for code that is not opted in to the newer behavior,
18+
// the old (buggy) behavior persists.
19+
20+
parameterUnmodified(int? x) {
21+
{
22+
late final b = x != null;
23+
// We wouldn't promote based on the initializers of late locals anyhow,
24+
// because we don't know when they execute.
25+
if (b) x.expectStaticType<Exactly<int?>>();
26+
}
27+
{
28+
late final b;
29+
b = x != null;
30+
if (b) x.expectStaticType<Exactly<int>>();
31+
}
32+
{
33+
late var b = x != null;
34+
// We wouldn't promote based on the initializers of late locals anyhow,
35+
// because we don't know when they execute.
36+
if (b) x.expectStaticType<Exactly<int?>>();
37+
}
38+
{
39+
late var b;
40+
b = x != null;
41+
if (b) x.expectStaticType<Exactly<int>>();
42+
}
43+
{
44+
final b = x != null;
45+
if (b) x.expectStaticType<Exactly<int?>>();
46+
}
47+
{
48+
final b;
49+
b = x != null;
50+
if (b) x.expectStaticType<Exactly<int>>();
51+
}
52+
{
53+
var b = x != null;
54+
if (b) x.expectStaticType<Exactly<int?>>();
55+
}
56+
{
57+
var b;
58+
b = x != null;
59+
if (b) x.expectStaticType<Exactly<int>>();
60+
}
61+
}
62+
63+
parameterModifiedLater(int? x, int? y) {
64+
x = y;
65+
{
66+
late final b = x != null;
67+
// We wouldn't promote based on the initializers of late locals anyhow,
68+
// because we don't know when they execute.
69+
if (b) x.expectStaticType<Exactly<int?>>();
70+
}
71+
{
72+
late final b;
73+
b = x != null;
74+
if (b) x.expectStaticType<Exactly<int>>();
75+
}
76+
{
77+
late var b = x != null;
78+
// We wouldn't promote based on the initializers of late locals anyhow,
79+
// because we don't know when they execute.
80+
if (b) x.expectStaticType<Exactly<int?>>();
81+
}
82+
{
83+
late var b;
84+
b = x != null;
85+
if (b) x.expectStaticType<Exactly<int>>();
86+
}
87+
{
88+
final b = x != null;
89+
if (b) x.expectStaticType<Exactly<int?>>();
90+
}
91+
{
92+
final b;
93+
b = x != null;
94+
if (b) x.expectStaticType<Exactly<int>>();
95+
}
96+
{
97+
var b = x != null;
98+
if (b) x.expectStaticType<Exactly<int?>>();
99+
}
100+
{
101+
var b;
102+
b = x != null;
103+
if (b) x.expectStaticType<Exactly<int>>();
104+
}
105+
}
106+
107+
localVariableInitialized(int? y) {
108+
int? x = y;
109+
{
110+
late final b = x != null;
111+
// We wouldn't promote based on the initializers of late locals anyhow,
112+
// because we don't know when they execute.
113+
if (b) x.expectStaticType<Exactly<int?>>();
114+
}
115+
{
116+
late final b;
117+
b = x != null;
118+
if (b) x.expectStaticType<Exactly<int>>();
119+
}
120+
{
121+
late var b = x != null;
122+
// We wouldn't promote based on the initializers of late locals anyhow,
123+
// because we don't know when they execute.
124+
if (b) x.expectStaticType<Exactly<int?>>();
125+
}
126+
{
127+
late var b;
128+
b = x != null;
129+
if (b) x.expectStaticType<Exactly<int>>();
130+
}
131+
{
132+
final b = x != null;
133+
if (b) x.expectStaticType<Exactly<int?>>();
134+
}
135+
{
136+
final b;
137+
b = x != null;
138+
if (b) x.expectStaticType<Exactly<int>>();
139+
}
140+
{
141+
var b = x != null;
142+
if (b) x.expectStaticType<Exactly<int?>>();
143+
}
144+
{
145+
var b;
146+
b = x != null;
147+
if (b) x.expectStaticType<Exactly<int>>();
148+
}
149+
}
150+
151+
localVariableModifiedLater(int? y) {
152+
int? x;
153+
x = y;
154+
{
155+
late final b = x != null;
156+
// We wouldn't promote based on the initializers of late locals anyhow,
157+
// because we don't know when they execute.
158+
if (b) x.expectStaticType<Exactly<int?>>();
159+
}
160+
{
161+
late final b;
162+
b = x != null;
163+
if (b) x.expectStaticType<Exactly<int>>();
164+
}
165+
{
166+
late var b = x != null;
167+
// We wouldn't promote based on the initializers of late locals anyhow,
168+
// because we don't know when they execute.
169+
if (b) x.expectStaticType<Exactly<int?>>();
170+
}
171+
{
172+
late var b;
173+
b = x != null;
174+
if (b) x.expectStaticType<Exactly<int>>();
175+
}
176+
{
177+
final b = x != null;
178+
if (b) x.expectStaticType<Exactly<int?>>();
179+
}
180+
{
181+
final b;
182+
b = x != null;
183+
if (b) x.expectStaticType<Exactly<int>>();
184+
}
185+
{
186+
var b = x != null;
187+
if (b) x.expectStaticType<Exactly<int?>>();
188+
}
189+
{
190+
var b;
191+
b = x != null;
192+
if (b) x.expectStaticType<Exactly<int>>();
193+
}
194+
}
195+
196+
main() {
197+
parameterUnmodified(null);
198+
parameterUnmodified(0);
199+
parameterModifiedLater(null, null);
200+
parameterModifiedLater(null, 0);
201+
localVariableInitialized(null);
202+
localVariableInitialized(0);
203+
localVariableModifiedLater(null);
204+
localVariableModifiedLater(0);
205+
}

0 commit comments

Comments
 (0)