Skip to content

Commit b13dea3

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Reland "Flow analysis: track property get targets."
This is a reland of bc6cdf5 Original change's description: > Flow analysis: track property get targets. > > These targets are needed for "why not promoted" error messages, and > it's easier to have flow analysis keep track of them than to have the > analyzer and CFE try to reconstruct them at the time of reporting the > error. > > Bug: #44898 > Change-Id: Ia8ef4a7ce13cc30860e59b7369e6230d233e252d > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193832 > Commit-Queue: Paul Berry <[email protected]> > Reviewed-by: Johnni Winther <[email protected]> > Reviewed-by: Konstantin Shcheglov <[email protected]> Bug: #44898 Change-Id: Ib5e6a0eafb381f3a9c8770c6c1c3e55581e44b01 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194105 Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Johnni Winther <[email protected]> Reviewed-by: William Hesse <[email protected]>
1 parent 4b59bf5 commit b13dea3

13 files changed

+121
-121
lines changed

pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,13 @@ abstract class FlowAnalysis<Node extends Object, Statement extends Node,
736736
/// expression to the left hand side of the `.`, and [propertyName] should be
737737
/// the identifier to the right hand side of the `.`. [staticType] should be
738738
/// the static type of the value returned by the property get.
739+
///
740+
/// [propertyMember] should be whatever data structure the client uses to keep
741+
/// track of the field or property being accessed. In the event of
742+
/// non-promotion of a property get, this value can be retrieved from
743+
/// [PropertyNotPromoted.propertyMember].
739744
void propertyGet(Expression wholeExpression, Expression target,
740-
String propertyName, Type staticType);
745+
String propertyName, Object? propertyMember, Type staticType);
741746

742747
/// Retrieves the SSA node associated with [variable], or `null` if [variable]
743748
/// is not associated with an SSA node because it is write captured. For
@@ -788,8 +793,13 @@ abstract class FlowAnalysis<Node extends Object, Statement extends Node,
788793
/// the whole property get, and [propertyName] should be the name of the
789794
/// property being read. [staticType] should be the static type of the value
790795
/// returned by the property get.
791-
void thisOrSuperPropertyGet(
792-
Expression expression, String propertyName, Type staticType);
796+
///
797+
/// [propertyMember] should be whatever data structure the client uses to keep
798+
/// track of the field or property being accessed. In the event of
799+
/// non-promotion of a property get, this value can be retrieved from
800+
/// [PropertyNotPromoted.propertyMember].
801+
void thisOrSuperPropertyGet(Expression expression, String propertyName,
802+
Object? propertyMember, Type staticType);
793803

794804
/// Call this method just before visiting the body of a "try/catch" statement.
795805
///
@@ -1339,11 +1349,12 @@ class FlowAnalysisDebug<Node extends Object, Statement extends Node,
13391349

13401350
@override
13411351
void propertyGet(Expression wholeExpression, Expression target,
1342-
String propertyName, Type staticType) {
1352+
String propertyName, Object? propertyMember, Type staticType) {
13431353
_wrap(
1344-
'propertyGet($wholeExpression, $target, $propertyName, $staticType)',
1354+
'propertyGet($wholeExpression, $target, $propertyName, '
1355+
'$propertyMember, $staticType)',
13451356
() => _wrapped.propertyGet(
1346-
wholeExpression, target, propertyName, staticType));
1357+
wholeExpression, target, propertyName, propertyMember, staticType));
13471358
}
13481359

13491360
@override
@@ -1378,12 +1389,13 @@ class FlowAnalysisDebug<Node extends Object, Statement extends Node,
13781389
}
13791390

13801391
@override
1381-
void thisOrSuperPropertyGet(
1382-
Expression expression, String propertyName, Type staticType) {
1392+
void thisOrSuperPropertyGet(Expression expression, String propertyName,
1393+
Object? propertyMember, Type staticType) {
13831394
_wrap(
1384-
'thisOrSuperPropertyGet($expression, $propertyName, $staticType)',
1395+
'thisOrSuperPropertyGet($expression, $propertyName, $propertyMember, '
1396+
'$staticType)',
13851397
() => _wrapped.thisOrSuperPropertyGet(
1386-
expression, propertyName, staticType));
1398+
expression, propertyName, propertyMember, staticType));
13871399
}
13881400

13891401
@override
@@ -2334,12 +2346,17 @@ class PropertyNotPromoted<Type extends Object> extends NonPromotionReason {
23342346
/// The name of the property.
23352347
final String propertyName;
23362348

2349+
/// The field or property being accessed. This matches a `propertyMember`
2350+
/// value that was passed to either [FlowAnalysis.propertyGet] or
2351+
/// [FlowAnalysis.thisOrSuperPropertyGet].
2352+
final Object? propertyMember;
2353+
23372354
/// The static type of the property at the time of the access. This is the
23382355
/// type that was passed to [FlowAnalysis.whyNotPromoted]; it is provided to
23392356
/// the client as a convenience for ID testing.
23402357
final Type staticType;
23412358

2342-
PropertyNotPromoted(this.propertyName, this.staticType);
2359+
PropertyNotPromoted(this.propertyName, this.propertyMember, this.staticType);
23432360

23442361
@override
23452362
String get documentationLink => 'http://dart.dev/go/non-promo-property';
@@ -2517,8 +2534,10 @@ abstract class Reference<Variable extends Object, Type extends Object> {
25172534

25182535
/// Creates a reference representing a get of a property called [propertyName]
25192536
/// on the reference represented by `this`.
2520-
Reference<Variable, Type> propertyGet(String propertyName) =>
2521-
new _PropertyGetReference<Variable, Type>(this, propertyName);
2537+
Reference<Variable, Type> propertyGet(
2538+
String propertyName, Object? propertyMember) =>
2539+
new _PropertyGetReference<Variable, Type>(
2540+
this, propertyName, propertyMember);
25222541

25232542
/// Stores info for this reference in [variableInfo].
25242543
void storeInfo(Map<Variable?, VariableModel<Variable, Type>> variableInfo,
@@ -3952,14 +3971,14 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
39523971

39533972
@override
39543973
void propertyGet(Expression wholeExpression, Expression target,
3955-
String propertyName, Type staticType) {
3974+
String propertyName, Object? propertyMember, Type staticType) {
39563975
Reference<Variable, Type>? reference =
39573976
_getExpressionReference(target)?.reference;
39583977
if (reference != null) {
39593978
_storeExpressionReference(
39603979
wholeExpression,
39613980
new ReferenceWithType<Variable, Type>(
3962-
reference.propertyGet(propertyName), staticType));
3981+
reference.propertyGet(propertyName, propertyMember), staticType));
39633982
}
39643983
}
39653984

@@ -4016,12 +4035,13 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
40164035
}
40174036

40184037
@override
4019-
void thisOrSuperPropertyGet(
4020-
Expression expression, String propertyName, Type staticType) {
4038+
void thisOrSuperPropertyGet(Expression expression, String propertyName,
4039+
Object? propertyMember, Type staticType) {
40214040
_storeExpressionReference(
40224041
expression,
40234042
new ReferenceWithType<Variable, Type>(
4024-
new _ThisReference<Variable, Type>().propertyGet(propertyName),
4043+
new _ThisReference<Variable, Type>()
4044+
.propertyGet(propertyName, propertyMember),
40254045
staticType));
40264046
}
40274047

@@ -4686,7 +4706,7 @@ class _LegacyTypePromotion<Node extends Object, Statement extends Node,
46864706

46874707
@override
46884708
void propertyGet(Expression wholeExpression, Expression target,
4689-
String propertyName, Type staticType) {}
4709+
String propertyName, Object? propertyMember, Type staticType) {}
46904710

46914711
@override
46924712
SsaNode<Variable, Type>? ssaNodeForTesting(Variable variable) {
@@ -4706,8 +4726,8 @@ class _LegacyTypePromotion<Node extends Object, Statement extends Node,
47064726
void thisOrSuper(Expression expression, Type staticType) {}
47074727

47084728
@override
4709-
void thisOrSuperPropertyGet(
4710-
Expression expression, String propertyName, Type staticType) {}
4729+
void thisOrSuperPropertyGet(Expression expression, String propertyName,
4730+
Object? propertyMember, Type staticType) {}
47114731

47124732
@override
47134733
void tryCatchStatement_bodyBegin() {}
@@ -4908,7 +4928,12 @@ class _PropertyGetReference<Variable extends Object, Type extends Object>
49084928
/// The name of the property.
49094929
final String propertyName;
49104930

4911-
_PropertyGetReference(this.target, this.propertyName);
4931+
/// The field or property being accessed. This matches a `propertyMember`
4932+
/// value that was passed to either [FlowAnalysis.propertyGet] or
4933+
/// [FlowAnalysis.thisOrSuperPropertyGet].
4934+
final Object? propertyMember;
4935+
4936+
_PropertyGetReference(this.target, this.propertyName, this.propertyMember);
49124937

49134938
@override
49144939
Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
@@ -4920,7 +4945,8 @@ class _PropertyGetReference<Variable extends Object, Type extends Object>
49204945
return () {
49214946
Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
49224947
for (Type type in promotedTypes) {
4923-
result[type] = new PropertyNotPromoted(propertyName, staticType);
4948+
result[type] =
4949+
new PropertyNotPromoted(propertyName, propertyMember, staticType);
49244950
}
49254951
return result;
49264952
};

pkg/_fe_analyzer_shared/test/mini_ast.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,7 +1510,7 @@ class _Property extends LValue {
15101510
Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
15111511
var targetType = target._visit(h, flow);
15121512
var propertyType = h.getMember(targetType, propertyName);
1513-
flow.propertyGet(this, target, propertyName, propertyType);
1513+
flow.propertyGet(this, target, propertyName, propertyName, propertyType);
15141514
return propertyType;
15151515
}
15161516

@@ -1614,7 +1614,7 @@ class _ThisOrSuperPropertyGet extends Expression {
16141614
@override
16151615
Type _visit(
16161616
Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
1617-
flow.thisOrSuperPropertyGet(this, propertyName, type);
1617+
flow.thisOrSuperPropertyGet(this, propertyName, propertyName, type);
16181618
return type;
16191619
}
16201620
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ class AssignmentExpressionResolver {
121121
CompileTimeErrorCode.INVALID_ASSIGNMENT,
122122
right,
123123
[rightType, writeType],
124-
_resolver.computeWhyNotPromotedMessages(
125-
right, right, whyNotPromoted?.call()),
124+
_resolver.computeWhyNotPromotedMessages(right, whyNotPromoted?.call()),
126125
);
127126
}
128127

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,11 @@ class MethodInvocationResolver {
807807
);
808808
}
809809
_resolver.flowAnalysis?.flow?.propertyGet(
810-
functionExpression, target, node.methodName.name, getterReturnType);
810+
functionExpression,
811+
target,
812+
node.methodName.name,
813+
node.methodName.staticElement,
814+
getterReturnType);
811815
functionExpression.staticType = targetType;
812816
}
813817

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ class PropertyElementResolver {
203203
readElementRequested = readLookup.requested;
204204
if (readElementRequested is PropertyAccessorElement &&
205205
!readElementRequested.isStatic) {
206-
_resolver.flowAnalysis?.flow?.thisOrSuperPropertyGet(
207-
node, node.name, readElementRequested.returnType);
206+
_resolver.flowAnalysis?.flow?.thisOrSuperPropertyGet(node, node.name,
207+
readElementRequested, readElementRequested.returnType);
208208
}
209209
_resolver.checkReadOfNotAssignedLocalVariable(node, readElementRequested);
210210
}
@@ -373,7 +373,11 @@ class PropertyElementResolver {
373373
nameErrorEntity: propertyName,
374374
);
375375

376-
_resolver.flowAnalysis?.flow?.propertyGet(node, target, propertyName.name,
376+
_resolver.flowAnalysis?.flow?.propertyGet(
377+
node,
378+
target,
379+
propertyName.name,
380+
result.getter,
377381
result.getter?.returnType ?? _typeSystem.typeProvider.dynamicType);
378382

379383
if (hasRead && result.needsGetterError) {
@@ -653,6 +657,7 @@ class PropertyElementResolver {
653657
node,
654658
target,
655659
propertyName.name,
660+
readElement,
656661
readElement?.returnType ?? _typeSystem.typeProvider.dynamicType);
657662
}
658663

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,11 @@ class TypePropertyResolver {
130130
if (flow != null) {
131131
if (receiver != null) {
132132
messages = _resolver.computeWhyNotPromotedMessages(
133-
receiver, nameErrorEntity, flow.whyNotPromoted(receiver)());
133+
nameErrorEntity, flow.whyNotPromoted(receiver)());
134134
} else {
135135
var thisType = _resolver.thisType;
136136
if (thisType != null) {
137-
messages = _resolver.computeWhyNotPromotedMessages(receiver,
137+
messages = _resolver.computeWhyNotPromotedMessages(
138138
nameErrorEntity, flow.whyNotPromotedImplicitThis(thisType)());
139139
}
140140
}

pkg/analyzer/lib/src/error/bool_expression_verifier.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class BoolExpressionVerifier {
5757
errorCode: CompileTimeErrorCode
5858
.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
5959
messages: _resolver.computeWhyNotPromotedMessages(
60-
expression, expression, whyNotPromoted?.call()));
60+
expression, whyNotPromoted?.call()));
6161
} else {
6262
_errorReporter.reportErrorForNode(errorCode, expression, arguments);
6363
}

pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ class NullableDereferenceVerifier {
7676

7777
List<DiagnosticMessage>? messages;
7878
if (errorNode is Expression) {
79-
messages = _resolver.computeWhyNotPromotedMessages(errorNode, errorNode,
80-
_resolver.flowAnalysis?.flow?.whyNotPromoted(errorNode)());
79+
messages = _resolver.computeWhyNotPromotedMessages(
80+
errorNode, _resolver.flowAnalysis?.flow?.whyNotPromoted(errorNode)());
8181
}
8282
report(errorNode, receiverType, errorCode: errorCode, messages: messages);
8383
return true;

pkg/analyzer/lib/src/generated/error_detection_helpers.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ mixin ErrorDetectionHelpers {
8585
}
8686
return;
8787
}
88-
var messages = computeWhyNotPromotedMessages(
89-
expression, expression, whyNotPromoted?.call());
88+
var messages =
89+
computeWhyNotPromotedMessages(expression, whyNotPromoted?.call());
9090
// report problem
9191
if (isConstConstructor) {
9292
// TODO(paulberry): this error should be based on the actual type of the
@@ -229,7 +229,6 @@ mixin ErrorDetectionHelpers {
229229
/// [whyNotPromoted] should be the non-promotion details returned by the flow
230230
/// analysis engine.
231231
List<DiagnosticMessage> computeWhyNotPromotedMessages(
232-
Expression? expression,
233232
SyntacticEntity errorEntity,
234233
Map<DartType, NonPromotionReason>? whyNotPromoted);
235234

@@ -313,8 +312,7 @@ mixin ErrorDetectionHelpers {
313312
errorCode,
314313
getErrorNode(expression),
315314
[actualStaticType, expectedStaticType],
316-
computeWhyNotPromotedMessages(
317-
expression, expression, whyNotPromoted?.call()),
315+
computeWhyNotPromotedMessages(expression, whyNotPromoted?.call()),
318316
);
319317
return false;
320318
}

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
312312

313313
@override
314314
List<DiagnosticMessage> computeWhyNotPromotedMessages(
315-
Expression? expression,
316315
SyntacticEntity errorEntity,
317316
Map<DartType, NonPromotionReason>? whyNotPromoted) {
318317
return [];

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

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -533,17 +533,13 @@ class ResolverVisitor extends ScopedVisitor with ErrorDetectionHelpers {
533533

534534
@override
535535
List<DiagnosticMessage> computeWhyNotPromotedMessages(
536-
Expression? expression,
537536
SyntacticEntity errorEntity,
538537
Map<DartType, NonPromotionReason>? whyNotPromoted) {
539-
if (expression is NamedExpression) {
540-
expression = expression.expression;
541-
}
542538
List<DiagnosticMessage> messages = [];
543539
if (whyNotPromoted != null) {
544540
for (var entry in whyNotPromoted.entries) {
545541
var whyNotPromotedVisitor = _WhyNotPromotedVisitor(
546-
source, expression, errorEntity, flowAnalysis!.dataForTesting);
542+
source, errorEntity, flowAnalysis!.dataForTesting);
547543
if (typeSystem.isPotentiallyNullable(entry.key)) continue;
548544
var message = entry.value.accept(whyNotPromotedVisitor);
549545
if (message != null) {
@@ -3447,10 +3443,6 @@ class _WhyNotPromotedVisitor
34473443
PromotableElement, DartType> {
34483444
final Source source;
34493445

3450-
/// The expression that was not promoted, or `null` if the thing that was not
3451-
/// promoted was an implicit `this`.
3452-
final Expression? _expression;
3453-
34543446
final SyntacticEntity _errorEntity;
34553447

34563448
final FlowAnalysisDataForTesting? _dataForTesting;
@@ -3459,8 +3451,7 @@ class _WhyNotPromotedVisitor
34593451

34603452
DartType? propertyType;
34613453

3462-
_WhyNotPromotedVisitor(
3463-
this.source, this._expression, this._errorEntity, this._dataForTesting);
3454+
_WhyNotPromotedVisitor(this.source, this._errorEntity, this._dataForTesting);
34643455

34653456
@override
34663457
DiagnosticMessage? visitDemoteViaExplicitWrite(
@@ -3480,18 +3471,7 @@ class _WhyNotPromotedVisitor
34803471
@override
34813472
DiagnosticMessage? visitPropertyNotPromoted(
34823473
PropertyNotPromoted<DartType> reason) {
3483-
var expression = _expression;
3484-
Element? receiverElement;
3485-
if (expression is SimpleIdentifier) {
3486-
receiverElement = expression.staticElement;
3487-
} else if (expression is PropertyAccess) {
3488-
receiverElement = expression.propertyName.staticElement;
3489-
} else if (expression is PrefixedIdentifier) {
3490-
receiverElement = expression.identifier.staticElement;
3491-
} else {
3492-
assert(false,
3493-
'Unrecognized property access expression: ${expression.runtimeType}');
3494-
}
3474+
var receiverElement = reason.propertyMember;
34953475
if (receiverElement is PropertyAccessorElement) {
34963476
propertyReference = receiverElement;
34973477
propertyType = reason.staticType;

0 commit comments

Comments
 (0)