Skip to content

Commit dd91769

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Flow analysis: implement "why not promoted" functionality for arguments.
Bug: #44898 Change-Id: Ib39ef04aadc2340c269878763e19a4a97001e2b5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/191989 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 00c188b commit dd91769

10 files changed

+424
-157
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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 `ArgumentTypeNotAssignableNullability` error, for which we wish to
7+
// report "why not promoted" context information.
8+
9+
class C1 {
10+
int? bad;
11+
f(int i) {}
12+
}
13+
14+
required_unnamed(C1 c) {
15+
if (c.bad == null) return;
16+
c.f(
17+
/*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: int?))*/ c
18+
. /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: int?))*/ bad);
19+
}
20+
21+
class C2 {
22+
int? bad;
23+
f([int i = 0]) {}
24+
}
25+
26+
optional_unnamed(C2 c) {
27+
if (c.bad == null) return;
28+
c.f(
29+
/*analyzer.notPromoted(propertyNotPromoted(target: member:C2.bad, type: int?))*/ c
30+
. /*cfe.notPromoted(propertyNotPromoted(target: member:C2.bad, type: int?))*/ bad);
31+
}
32+
33+
class C3 {
34+
int? bad;
35+
f({required int i}) {}
36+
}
37+
38+
required_named(C3 c) {
39+
if (c.bad == null) return;
40+
c.f(
41+
/*analyzer.notPromoted(propertyNotPromoted(target: member:C3.bad, type: int?))*/ i:
42+
c. /*cfe.notPromoted(propertyNotPromoted(target: member:C3.bad, type: int?))*/ bad);
43+
}
44+
45+
class C4 {
46+
int? bad;
47+
f({int i = 0}) {}
48+
}
49+
50+
optional_named(C4 c) {
51+
if (c.bad == null) return;
52+
c.f(
53+
/*analyzer.notPromoted(propertyNotPromoted(target: member:C4.bad, type: int?))*/ i:
54+
c. /*cfe.notPromoted(propertyNotPromoted(target: member:C4.bad, type: int?))*/ bad);
55+
}
56+
57+
class C5 {
58+
List<int>? bad;
59+
f<T>(List<T> x) {}
60+
}
61+
62+
type_inferred(C5 c) {
63+
if (c.bad == null) return;
64+
c.f(
65+
/*analyzer.notPromoted(propertyNotPromoted(target: member:C5.bad, type: List<int>?))*/ c
66+
. /*cfe.notPromoted(propertyNotPromoted(target: member:C5.bad, type: List<int>?))*/ bad);
67+
}
68+
69+
class C6 {
70+
int? bad;
71+
C6(int i);
72+
}
73+
74+
C6 constructor_with_implicit_new(C6 c) {
75+
if (c.bad == null) return;
76+
return C6(
77+
/*analyzer.notPromoted(propertyNotPromoted(target: member:C6.bad, type: int?))*/ c
78+
. /*cfe.notPromoted(propertyNotPromoted(target: member:C6.bad, type: int?))*/ bad);
79+
}
80+
81+
class C7 {
82+
int? bad;
83+
C7(int i);
84+
}
85+
86+
C7 constructor_with_explicit_new(C7 c) {
87+
if (c.bad == null) return;
88+
return new C7(
89+
/*analyzer.notPromoted(propertyNotPromoted(target: member:C7.bad, type: int?))*/ c
90+
. /*cfe.notPromoted(propertyNotPromoted(target: member:C7.bad, type: int?))*/ bad);
91+
}

pkg/analyzer/lib/src/dart/analysis/driver.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ import 'package:meta/meta.dart';
8080
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
8181
class AnalysisDriver implements AnalysisDriverGeneric {
8282
/// The version of data format, should be incremented on every format change.
83-
static const int DATA_VERSION = 132;
83+
static const int DATA_VERSION = 133;
8484

8585
/// The length of the list returned by [_computeDeclaredVariablesSignature].
8686
static const int _declaredVariablesSignatureLength = 4;

pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart

+45-23
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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+
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
56
import 'package:analyzer/dart/analysis/features.dart';
67
import 'package:analyzer/dart/ast/ast.dart';
78
import 'package:analyzer/dart/element/element.dart';
@@ -28,11 +29,12 @@ class AnnotationResolver {
2829
bool get _genericMetadataIsEnabled =>
2930
_definingLibrary.featureSet.isEnabled(Feature.generic_metadata);
3031

31-
void resolve(AnnotationImpl node) {
32+
void resolve(AnnotationImpl node,
33+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
3234
AstNode parent = node.parent;
3335

3436
node.typeArguments?.accept(_resolver);
35-
_resolve(node);
37+
_resolve(node, whyNotPromotedInfo);
3638

3739
var elementAnnotationImpl =
3840
node.elementAnnotation as ElementAnnotationImpl?;
@@ -48,6 +50,7 @@ class AnnotationResolver {
4850
AnnotationImpl node,
4951
ClassElement classElement,
5052
SimpleIdentifierImpl? getterName,
53+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
5154
) {
5255
ExecutableElement? getter;
5356
if (getterName != null) {
@@ -63,7 +66,7 @@ class AnnotationResolver {
6366
node.element = getter;
6467

6568
if (getterName != null && getter is PropertyAccessorElement) {
66-
_propertyAccessorElement(node, getterName, getter);
69+
_propertyAccessorElement(node, getterName, getter, whyNotPromotedInfo);
6770
_resolveAnnotationElementGetter(node, getter);
6871
} else if (getter is! ConstructorElement) {
6972
_errorReporter.reportErrorForNode(
@@ -72,14 +75,15 @@ class AnnotationResolver {
7275
);
7376
}
7477

75-
node.arguments?.accept(_resolver);
78+
_visitArguments(node, whyNotPromotedInfo);
7679
}
7780

7881
void _constructorInvocation(
7982
AnnotationImpl node,
8083
ClassElement classElement,
8184
SimpleIdentifierImpl? constructorName,
8285
ArgumentList argumentList,
86+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
8387
) {
8488
ConstructorElement? constructorElement;
8589
if (constructorName != null) {
@@ -99,7 +103,8 @@ class AnnotationResolver {
99103
CompileTimeErrorCode.INVALID_ANNOTATION,
100104
node,
101105
);
102-
argumentList.accept(_resolver);
106+
_resolver.visitArgumentList(argumentList,
107+
whyNotPromotedInfo: whyNotPromotedInfo);
103108
return;
104109
}
105110

@@ -109,7 +114,8 @@ class AnnotationResolver {
109114
if (typeParameters.isEmpty) {
110115
_resolveConstructorInvocationArguments(node);
111116
InferenceContext.setType(argumentList, constructorElement.type);
112-
argumentList.accept(_resolver);
117+
_resolver.visitArgumentList(argumentList,
118+
whyNotPromotedInfo: whyNotPromotedInfo);
113119
return;
114120
}
115121

@@ -127,7 +133,8 @@ class AnnotationResolver {
127133
_resolveConstructorInvocationArguments(node);
128134

129135
InferenceContext.setType(argumentList, constructorElement.type);
130-
argumentList.accept(_resolver);
136+
_resolver.visitArgumentList(argumentList,
137+
whyNotPromotedInfo: whyNotPromotedInfo);
131138
}
132139

133140
if (!_genericMetadataIsEnabled) {
@@ -156,7 +163,8 @@ class AnnotationResolver {
156163
return;
157164
}
158165

159-
argumentList.accept(_resolver);
166+
_resolver.visitArgumentList(argumentList,
167+
whyNotPromotedInfo: whyNotPromotedInfo);
160168

161169
var constructorRawType = _resolver.typeAnalyzer
162170
.constructorToGenericFunctionType(constructorElement);
@@ -186,6 +194,7 @@ class AnnotationResolver {
186194
AnnotationImpl node,
187195
ExtensionElement extensionElement,
188196
SimpleIdentifierImpl? getterName,
197+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
189198
) {
190199
ExecutableElement? getter;
191200
if (getterName != null) {
@@ -197,7 +206,7 @@ class AnnotationResolver {
197206
node.element = getter;
198207

199208
if (getterName != null && getter is PropertyAccessorElement) {
200-
_propertyAccessorElement(node, getterName, getter);
209+
_propertyAccessorElement(node, getterName, getter, whyNotPromotedInfo);
201210
_resolveAnnotationElementGetter(node, getter);
202211
} else {
203212
_errorReporter.reportErrorForNode(
@@ -206,23 +215,25 @@ class AnnotationResolver {
206215
);
207216
}
208217

209-
node.arguments?.accept(_resolver);
218+
_visitArguments(node, whyNotPromotedInfo);
210219
}
211220

212221
void _propertyAccessorElement(
213222
AnnotationImpl node,
214223
SimpleIdentifierImpl name,
215224
PropertyAccessorElement element,
225+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
216226
) {
217227
element = _resolver.toLegacyElement(element);
218228
name.staticElement = element;
219229
node.element = element;
220230

221231
_resolveAnnotationElementGetter(node, element);
222-
node.arguments?.accept(_resolver);
232+
_visitArguments(node, whyNotPromotedInfo);
223233
}
224234

225-
void _resolve(AnnotationImpl node) {
235+
void _resolve(AnnotationImpl node,
236+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
226237
SimpleIdentifierImpl name1;
227238
SimpleIdentifierImpl? name2;
228239
SimpleIdentifierImpl? name3;
@@ -246,23 +257,24 @@ class AnnotationResolver {
246257
node,
247258
[name1.name],
248259
);
249-
node.arguments?.accept(_resolver);
260+
_visitArguments(node, whyNotPromotedInfo);
250261
return;
251262
}
252263

253264
// Class(args) or Class.CONST
254265
if (element1 is ClassElement) {
255266
if (argumentList != null) {
256-
_constructorInvocation(node, element1, name2, argumentList);
267+
_constructorInvocation(
268+
node, element1, name2, argumentList, whyNotPromotedInfo);
257269
} else {
258-
_classGetter(node, element1, name2);
270+
_classGetter(node, element1, name2, whyNotPromotedInfo);
259271
}
260272
return;
261273
}
262274

263275
// Extension.CONST
264276
if (element1 is ExtensionElement) {
265-
_extensionGetter(node, element1, name2);
277+
_extensionGetter(node, element1, name2, whyNotPromotedInfo);
266278
return;
267279
}
268280

@@ -274,20 +286,21 @@ class AnnotationResolver {
274286
// prefix.Class(args) or prefix.Class.CONST
275287
if (element2 is ClassElement) {
276288
if (argumentList != null) {
277-
_constructorInvocation(node, element2, name3, argumentList);
289+
_constructorInvocation(
290+
node, element2, name3, argumentList, whyNotPromotedInfo);
278291
} else {
279-
_classGetter(node, element2, name3);
292+
_classGetter(node, element2, name3, whyNotPromotedInfo);
280293
}
281294
return;
282295
}
283296
// prefix.Extension.CONST
284297
if (element2 is ExtensionElement) {
285-
_extensionGetter(node, element2, name3);
298+
_extensionGetter(node, element2, name3, whyNotPromotedInfo);
286299
return;
287300
}
288301
// prefix.CONST
289302
if (element2 is PropertyAccessorElement) {
290-
_propertyAccessorElement(node, name2, element2);
303+
_propertyAccessorElement(node, name2, element2, whyNotPromotedInfo);
291304
return;
292305
}
293306
// undefined
@@ -297,15 +310,15 @@ class AnnotationResolver {
297310
node,
298311
[name2.name],
299312
);
300-
node.arguments?.accept(_resolver);
313+
_visitArguments(node, whyNotPromotedInfo);
301314
return;
302315
}
303316
}
304317
}
305318

306319
// CONST
307320
if (element1 is PropertyAccessorElement) {
308-
_propertyAccessorElement(node, name1, element1);
321+
_propertyAccessorElement(node, name1, element1, whyNotPromotedInfo);
309322
return;
310323
}
311324

@@ -319,7 +332,7 @@ class AnnotationResolver {
319332
node,
320333
);
321334

322-
node.arguments?.accept(_resolver);
335+
_visitArguments(node, whyNotPromotedInfo);
323336
}
324337

325338
void _resolveAnnotationElementGetter(
@@ -379,4 +392,13 @@ class AnnotationResolver {
379392
}
380393
}
381394
}
395+
396+
void _visitArguments(AnnotationImpl node,
397+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
398+
var arguments = node.arguments;
399+
if (arguments != null) {
400+
_resolver.visitArgumentList(arguments,
401+
whyNotPromotedInfo: whyNotPromotedInfo);
402+
}
403+
}
382404
}

0 commit comments

Comments
 (0)