Revert "Flow analysis: track property get targets."
This reverts commit bc6cdf54fd.
Reason for revert: Broke Golem benchmarks - https://golem.corp.goog/PerformanceChanges?repository=dart&revision=91561
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: https://github.com/dart-lang/sdk/issues/44898
> Change-Id: Ia8ef4a7ce13cc30860e59b7369e6230d233e252d
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193832
> Commit-Queue: Paul Berry <paulberry@google.com>
> Reviewed-by: Johnni Winther <johnniwinther@google.com>
> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
TBR=paulberry@google.com,scheglov@google.com,johnniwinther@google.com
Change-Id: Ic2b66b1db621c0f4e4c5398acfe2ae61bd7625ca
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: https://github.com/dart-lang/sdk/issues/44898
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194104
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
fc349bdbb5
commit
cf7587a160
@@ -736,13 +736,8 @@ abstract class FlowAnalysis<Node extends Object, Statement extends Node,
|
||||
/// expression to the left hand side of the `.`, and [propertyName] should be
|
||||
/// the identifier to the right hand side of the `.`. [staticType] should be
|
||||
/// the static type of the value returned by the property get.
|
||||
///
|
||||
/// [propertyMember] should be whatever data structure the client uses to keep
|
||||
/// track of the field or property being accessed. In the event of
|
||||
/// non-promotion of a property get, this value can be retrieved from
|
||||
/// [PropertyNotPromoted.propertyMember].
|
||||
void propertyGet(Expression wholeExpression, Expression target,
|
||||
String propertyName, Object? propertyMember, Type staticType);
|
||||
String propertyName, Type staticType);
|
||||
|
||||
/// Retrieves the SSA node associated with [variable], or `null` if [variable]
|
||||
/// is not associated with an SSA node because it is write captured. For
|
||||
@@ -793,13 +788,8 @@ abstract class FlowAnalysis<Node extends Object, Statement extends Node,
|
||||
/// the whole property get, and [propertyName] should be the name of the
|
||||
/// property being read. [staticType] should be the static type of the value
|
||||
/// returned by the property get.
|
||||
///
|
||||
/// [propertyMember] should be whatever data structure the client uses to keep
|
||||
/// track of the field or property being accessed. In the event of
|
||||
/// non-promotion of a property get, this value can be retrieved from
|
||||
/// [PropertyNotPromoted.propertyMember].
|
||||
void thisOrSuperPropertyGet(Expression expression, String propertyName,
|
||||
Object? propertyMember, Type staticType);
|
||||
void thisOrSuperPropertyGet(
|
||||
Expression expression, String propertyName, Type staticType);
|
||||
|
||||
/// Call this method just before visiting the body of a "try/catch" statement.
|
||||
///
|
||||
@@ -1349,12 +1339,11 @@ class FlowAnalysisDebug<Node extends Object, Statement extends Node,
|
||||
|
||||
@override
|
||||
void propertyGet(Expression wholeExpression, Expression target,
|
||||
String propertyName, Object? propertyMember, Type staticType) {
|
||||
String propertyName, Type staticType) {
|
||||
_wrap(
|
||||
'propertyGet($wholeExpression, $target, $propertyName, '
|
||||
'$propertyMember, $staticType)',
|
||||
'propertyGet($wholeExpression, $target, $propertyName, $staticType)',
|
||||
() => _wrapped.propertyGet(
|
||||
wholeExpression, target, propertyName, propertyMember, staticType));
|
||||
wholeExpression, target, propertyName, staticType));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1389,13 +1378,12 @@ class FlowAnalysisDebug<Node extends Object, Statement extends Node,
|
||||
}
|
||||
|
||||
@override
|
||||
void thisOrSuperPropertyGet(Expression expression, String propertyName,
|
||||
Object? propertyMember, Type staticType) {
|
||||
void thisOrSuperPropertyGet(
|
||||
Expression expression, String propertyName, Type staticType) {
|
||||
_wrap(
|
||||
'thisOrSuperPropertyGet($expression, $propertyName, $propertyMember, '
|
||||
'$staticType)',
|
||||
'thisOrSuperPropertyGet($expression, $propertyName, $staticType)',
|
||||
() => _wrapped.thisOrSuperPropertyGet(
|
||||
expression, propertyName, propertyMember, staticType));
|
||||
expression, propertyName, staticType));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -2346,17 +2334,12 @@ class PropertyNotPromoted<Type extends Object> extends NonPromotionReason {
|
||||
/// The name of the property.
|
||||
final String propertyName;
|
||||
|
||||
/// The field or property being accessed. This matches a `propertyMember`
|
||||
/// value that was passed to either [FlowAnalysis.propertyGet] or
|
||||
/// [FlowAnalysis.thisOrSuperPropertyGet].
|
||||
final Object? propertyMember;
|
||||
|
||||
/// The static type of the property at the time of the access. This is the
|
||||
/// type that was passed to [FlowAnalysis.whyNotPromoted]; it is provided to
|
||||
/// the client as a convenience for ID testing.
|
||||
final Type staticType;
|
||||
|
||||
PropertyNotPromoted(this.propertyName, this.propertyMember, this.staticType);
|
||||
PropertyNotPromoted(this.propertyName, this.staticType);
|
||||
|
||||
@override
|
||||
String get documentationLink => 'http://dart.dev/go/non-promo-property';
|
||||
@@ -2534,10 +2517,8 @@ abstract class Reference<Variable extends Object, Type extends Object> {
|
||||
|
||||
/// Creates a reference representing a get of a property called [propertyName]
|
||||
/// on the reference represented by `this`.
|
||||
Reference<Variable, Type> propertyGet(
|
||||
String propertyName, Object? propertyMember) =>
|
||||
new _PropertyGetReference<Variable, Type>(
|
||||
this, propertyName, propertyMember);
|
||||
Reference<Variable, Type> propertyGet(String propertyName) =>
|
||||
new _PropertyGetReference<Variable, Type>(this, propertyName);
|
||||
|
||||
/// Stores info for this reference in [variableInfo].
|
||||
void storeInfo(Map<Variable?, VariableModel<Variable, Type>> variableInfo,
|
||||
@@ -3971,14 +3952,14 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
|
||||
|
||||
@override
|
||||
void propertyGet(Expression wholeExpression, Expression target,
|
||||
String propertyName, Object? propertyMember, Type staticType) {
|
||||
String propertyName, Type staticType) {
|
||||
Reference<Variable, Type>? reference =
|
||||
_getExpressionReference(target)?.reference;
|
||||
if (reference != null) {
|
||||
_storeExpressionReference(
|
||||
wholeExpression,
|
||||
new ReferenceWithType<Variable, Type>(
|
||||
reference.propertyGet(propertyName, propertyMember), staticType));
|
||||
reference.propertyGet(propertyName), staticType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4035,13 +4016,12 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
|
||||
}
|
||||
|
||||
@override
|
||||
void thisOrSuperPropertyGet(Expression expression, String propertyName,
|
||||
Object? propertyMember, Type staticType) {
|
||||
void thisOrSuperPropertyGet(
|
||||
Expression expression, String propertyName, Type staticType) {
|
||||
_storeExpressionReference(
|
||||
expression,
|
||||
new ReferenceWithType<Variable, Type>(
|
||||
new _ThisReference<Variable, Type>()
|
||||
.propertyGet(propertyName, propertyMember),
|
||||
new _ThisReference<Variable, Type>().propertyGet(propertyName),
|
||||
staticType));
|
||||
}
|
||||
|
||||
@@ -4706,7 +4686,7 @@ class _LegacyTypePromotion<Node extends Object, Statement extends Node,
|
||||
|
||||
@override
|
||||
void propertyGet(Expression wholeExpression, Expression target,
|
||||
String propertyName, Object? propertyMember, Type staticType) {}
|
||||
String propertyName, Type staticType) {}
|
||||
|
||||
@override
|
||||
SsaNode<Variable, Type>? ssaNodeForTesting(Variable variable) {
|
||||
@@ -4726,8 +4706,8 @@ class _LegacyTypePromotion<Node extends Object, Statement extends Node,
|
||||
void thisOrSuper(Expression expression, Type staticType) {}
|
||||
|
||||
@override
|
||||
void thisOrSuperPropertyGet(Expression expression, String propertyName,
|
||||
Object? propertyMember, Type staticType) {}
|
||||
void thisOrSuperPropertyGet(
|
||||
Expression expression, String propertyName, Type staticType) {}
|
||||
|
||||
@override
|
||||
void tryCatchStatement_bodyBegin() {}
|
||||
@@ -4928,12 +4908,7 @@ class _PropertyGetReference<Variable extends Object, Type extends Object>
|
||||
/// The name of the property.
|
||||
final String propertyName;
|
||||
|
||||
/// The field or property being accessed. This matches a `propertyMember`
|
||||
/// value that was passed to either [FlowAnalysis.propertyGet] or
|
||||
/// [FlowAnalysis.thisOrSuperPropertyGet].
|
||||
final Object? propertyMember;
|
||||
|
||||
_PropertyGetReference(this.target, this.propertyName, this.propertyMember);
|
||||
_PropertyGetReference(this.target, this.propertyName);
|
||||
|
||||
@override
|
||||
Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
|
||||
@@ -4945,8 +4920,7 @@ class _PropertyGetReference<Variable extends Object, Type extends Object>
|
||||
return () {
|
||||
Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
|
||||
for (Type type in promotedTypes) {
|
||||
result[type] =
|
||||
new PropertyNotPromoted(propertyName, propertyMember, staticType);
|
||||
result[type] = new PropertyNotPromoted(propertyName, staticType);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -1510,7 +1510,7 @@ class _Property extends LValue {
|
||||
Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
|
||||
var targetType = target._visit(h, flow);
|
||||
var propertyType = h.getMember(targetType, propertyName);
|
||||
flow.propertyGet(this, target, propertyName, propertyName, propertyType);
|
||||
flow.propertyGet(this, target, propertyName, propertyType);
|
||||
return propertyType;
|
||||
}
|
||||
|
||||
@@ -1614,7 +1614,7 @@ class _ThisOrSuperPropertyGet extends Expression {
|
||||
@override
|
||||
Type _visit(
|
||||
Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
|
||||
flow.thisOrSuperPropertyGet(this, propertyName, propertyName, type);
|
||||
flow.thisOrSuperPropertyGet(this, propertyName, type);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,8 @@ class AssignmentExpressionResolver {
|
||||
CompileTimeErrorCode.INVALID_ASSIGNMENT,
|
||||
right,
|
||||
[rightType, writeType],
|
||||
_resolver.computeWhyNotPromotedMessages(right, whyNotPromoted?.call()),
|
||||
_resolver.computeWhyNotPromotedMessages(
|
||||
right, right, whyNotPromoted?.call()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -807,11 +807,7 @@ class MethodInvocationResolver {
|
||||
);
|
||||
}
|
||||
_resolver.flowAnalysis?.flow?.propertyGet(
|
||||
functionExpression,
|
||||
target,
|
||||
node.methodName.name,
|
||||
node.methodName.staticElement,
|
||||
getterReturnType);
|
||||
functionExpression, target, node.methodName.name, getterReturnType);
|
||||
functionExpression.staticType = targetType;
|
||||
}
|
||||
|
||||
|
||||
@@ -203,8 +203,8 @@ class PropertyElementResolver {
|
||||
readElementRequested = readLookup.requested;
|
||||
if (readElementRequested is PropertyAccessorElement &&
|
||||
!readElementRequested.isStatic) {
|
||||
_resolver.flowAnalysis?.flow?.thisOrSuperPropertyGet(node, node.name,
|
||||
readElementRequested, readElementRequested.returnType);
|
||||
_resolver.flowAnalysis?.flow?.thisOrSuperPropertyGet(
|
||||
node, node.name, readElementRequested.returnType);
|
||||
}
|
||||
_resolver.checkReadOfNotAssignedLocalVariable(node, readElementRequested);
|
||||
}
|
||||
@@ -373,11 +373,7 @@ class PropertyElementResolver {
|
||||
nameErrorEntity: propertyName,
|
||||
);
|
||||
|
||||
_resolver.flowAnalysis?.flow?.propertyGet(
|
||||
node,
|
||||
target,
|
||||
propertyName.name,
|
||||
result.getter,
|
||||
_resolver.flowAnalysis?.flow?.propertyGet(node, target, propertyName.name,
|
||||
result.getter?.returnType ?? _typeSystem.typeProvider.dynamicType);
|
||||
|
||||
if (hasRead && result.needsGetterError) {
|
||||
@@ -657,7 +653,6 @@ class PropertyElementResolver {
|
||||
node,
|
||||
target,
|
||||
propertyName.name,
|
||||
readElement,
|
||||
readElement?.returnType ?? _typeSystem.typeProvider.dynamicType);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,11 +130,11 @@ class TypePropertyResolver {
|
||||
if (flow != null) {
|
||||
if (receiver != null) {
|
||||
messages = _resolver.computeWhyNotPromotedMessages(
|
||||
nameErrorEntity, flow.whyNotPromoted(receiver)());
|
||||
receiver, nameErrorEntity, flow.whyNotPromoted(receiver)());
|
||||
} else {
|
||||
var thisType = _resolver.thisType;
|
||||
if (thisType != null) {
|
||||
messages = _resolver.computeWhyNotPromotedMessages(
|
||||
messages = _resolver.computeWhyNotPromotedMessages(receiver,
|
||||
nameErrorEntity, flow.whyNotPromotedImplicitThis(thisType)());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class BoolExpressionVerifier {
|
||||
errorCode: CompileTimeErrorCode
|
||||
.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
|
||||
messages: _resolver.computeWhyNotPromotedMessages(
|
||||
expression, whyNotPromoted?.call()));
|
||||
expression, expression, whyNotPromoted?.call()));
|
||||
} else {
|
||||
_errorReporter.reportErrorForNode(errorCode, expression, arguments);
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@ class NullableDereferenceVerifier {
|
||||
|
||||
List<DiagnosticMessage>? messages;
|
||||
if (errorNode is Expression) {
|
||||
messages = _resolver.computeWhyNotPromotedMessages(
|
||||
errorNode, _resolver.flowAnalysis?.flow?.whyNotPromoted(errorNode)());
|
||||
messages = _resolver.computeWhyNotPromotedMessages(errorNode, errorNode,
|
||||
_resolver.flowAnalysis?.flow?.whyNotPromoted(errorNode)());
|
||||
}
|
||||
report(errorNode, receiverType, errorCode: errorCode, messages: messages);
|
||||
return true;
|
||||
|
||||
@@ -85,8 +85,8 @@ mixin ErrorDetectionHelpers {
|
||||
}
|
||||
return;
|
||||
}
|
||||
var messages =
|
||||
computeWhyNotPromotedMessages(expression, whyNotPromoted?.call());
|
||||
var messages = computeWhyNotPromotedMessages(
|
||||
expression, expression, whyNotPromoted?.call());
|
||||
// report problem
|
||||
if (isConstConstructor) {
|
||||
// TODO(paulberry): this error should be based on the actual type of the
|
||||
@@ -229,6 +229,7 @@ mixin ErrorDetectionHelpers {
|
||||
/// [whyNotPromoted] should be the non-promotion details returned by the flow
|
||||
/// analysis engine.
|
||||
List<DiagnosticMessage> computeWhyNotPromotedMessages(
|
||||
Expression? expression,
|
||||
SyntacticEntity errorEntity,
|
||||
Map<DartType, NonPromotionReason>? whyNotPromoted);
|
||||
|
||||
@@ -312,7 +313,8 @@ mixin ErrorDetectionHelpers {
|
||||
errorCode,
|
||||
getErrorNode(expression),
|
||||
[actualStaticType, expectedStaticType],
|
||||
computeWhyNotPromotedMessages(expression, whyNotPromoted?.call()),
|
||||
computeWhyNotPromotedMessages(
|
||||
expression, expression, whyNotPromoted?.call()),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -312,6 +312,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
|
||||
@override
|
||||
List<DiagnosticMessage> computeWhyNotPromotedMessages(
|
||||
Expression? expression,
|
||||
SyntacticEntity errorEntity,
|
||||
Map<DartType, NonPromotionReason>? whyNotPromoted) {
|
||||
return [];
|
||||
|
||||
@@ -533,13 +533,17 @@ class ResolverVisitor extends ScopedVisitor with ErrorDetectionHelpers {
|
||||
|
||||
@override
|
||||
List<DiagnosticMessage> computeWhyNotPromotedMessages(
|
||||
Expression? expression,
|
||||
SyntacticEntity errorEntity,
|
||||
Map<DartType, NonPromotionReason>? whyNotPromoted) {
|
||||
if (expression is NamedExpression) {
|
||||
expression = expression.expression;
|
||||
}
|
||||
List<DiagnosticMessage> messages = [];
|
||||
if (whyNotPromoted != null) {
|
||||
for (var entry in whyNotPromoted.entries) {
|
||||
var whyNotPromotedVisitor = _WhyNotPromotedVisitor(
|
||||
source, errorEntity, flowAnalysis!.dataForTesting);
|
||||
source, expression, errorEntity, flowAnalysis!.dataForTesting);
|
||||
if (typeSystem.isPotentiallyNullable(entry.key)) continue;
|
||||
var message = entry.value.accept(whyNotPromotedVisitor);
|
||||
if (message != null) {
|
||||
@@ -3443,6 +3447,10 @@ class _WhyNotPromotedVisitor
|
||||
PromotableElement, DartType> {
|
||||
final Source source;
|
||||
|
||||
/// The expression that was not promoted, or `null` if the thing that was not
|
||||
/// promoted was an implicit `this`.
|
||||
final Expression? _expression;
|
||||
|
||||
final SyntacticEntity _errorEntity;
|
||||
|
||||
final FlowAnalysisDataForTesting? _dataForTesting;
|
||||
@@ -3451,7 +3459,8 @@ class _WhyNotPromotedVisitor
|
||||
|
||||
DartType? propertyType;
|
||||
|
||||
_WhyNotPromotedVisitor(this.source, this._errorEntity, this._dataForTesting);
|
||||
_WhyNotPromotedVisitor(
|
||||
this.source, this._expression, this._errorEntity, this._dataForTesting);
|
||||
|
||||
@override
|
||||
DiagnosticMessage? visitDemoteViaExplicitWrite(
|
||||
@@ -3471,7 +3480,18 @@ class _WhyNotPromotedVisitor
|
||||
@override
|
||||
DiagnosticMessage? visitPropertyNotPromoted(
|
||||
PropertyNotPromoted<DartType> reason) {
|
||||
var receiverElement = reason.propertyMember;
|
||||
var expression = _expression;
|
||||
Element? receiverElement;
|
||||
if (expression is SimpleIdentifier) {
|
||||
receiverElement = expression.staticElement;
|
||||
} else if (expression is PropertyAccess) {
|
||||
receiverElement = expression.propertyName.staticElement;
|
||||
} else if (expression is PrefixedIdentifier) {
|
||||
receiverElement = expression.identifier.staticElement;
|
||||
} else {
|
||||
assert(false,
|
||||
'Unrecognized property access expression: ${expression.runtimeType}');
|
||||
}
|
||||
if (receiverElement is PropertyAccessorElement) {
|
||||
propertyReference = receiverElement;
|
||||
propertyType = reason.staticType;
|
||||
|
||||
@@ -1480,6 +1480,7 @@ class InferenceVisitor
|
||||
replacement = inferrer.helper.buildProblem(
|
||||
messageNullableSpreadError, receiver.fileOffset, 1,
|
||||
context: inferrer.getWhyNotPromotedContext(
|
||||
receiver,
|
||||
inferrer.flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
element,
|
||||
(type) => !type.isPotentiallyNullable));
|
||||
@@ -1549,6 +1550,7 @@ class InferenceVisitor
|
||||
replacement = inferrer.helper.buildProblem(
|
||||
messageNullableSpreadError, receiver.fileOffset, 1,
|
||||
context: inferrer.getWhyNotPromotedContext(
|
||||
receiver,
|
||||
inferrer.flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
element,
|
||||
(type) => !type.isPotentiallyNullable));
|
||||
@@ -1986,6 +1988,7 @@ class InferenceVisitor
|
||||
Expression problem = inferrer.helper.buildProblem(
|
||||
messageNullableSpreadError, receiver.fileOffset, 1,
|
||||
context: inferrer.getWhyNotPromotedContext(
|
||||
receiver,
|
||||
inferrer.flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
entry,
|
||||
(type) => !type.isPotentiallyNullable));
|
||||
@@ -2005,6 +2008,7 @@ class InferenceVisitor
|
||||
receiver.fileOffset,
|
||||
1,
|
||||
context: inferrer.getWhyNotPromotedContext(
|
||||
receiver,
|
||||
inferrer.flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
entry,
|
||||
(type) => !type.isPotentiallyNullable));
|
||||
@@ -2115,6 +2119,7 @@ class InferenceVisitor
|
||||
keyError = inferrer.helper.buildProblem(
|
||||
messageNullableSpreadError, receiver.fileOffset, 1,
|
||||
context: inferrer.getWhyNotPromotedContext(
|
||||
receiver,
|
||||
inferrer.flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
entry,
|
||||
(type) => !type.isPotentiallyNullable));
|
||||
@@ -2879,9 +2884,8 @@ class InferenceVisitor
|
||||
}
|
||||
|
||||
ExpressionInferenceResult readResult = _computePropertyGet(node.readOffset,
|
||||
readReceiver, receiverType, node.propertyName, const UnknownType(),
|
||||
isThisReceiver: node.receiver is ThisExpression)
|
||||
.expressionInferenceResult;
|
||||
readReceiver, receiverType, node.propertyName, const UnknownType(),
|
||||
isThisReceiver: node.receiver is ThisExpression);
|
||||
|
||||
Expression read = readResult.expression;
|
||||
DartType readType = readResult.inferredType;
|
||||
@@ -2937,9 +2941,8 @@ class InferenceVisitor
|
||||
Expression writeReceiver = createVariableGet(receiverVariable);
|
||||
|
||||
ExpressionInferenceResult readResult = _computePropertyGet(node.readOffset,
|
||||
readReceiver, receiverType, node.propertyName, const UnknownType(),
|
||||
isThisReceiver: node.receiver is ThisExpression)
|
||||
.expressionInferenceResult;
|
||||
readReceiver, receiverType, node.propertyName, const UnknownType(),
|
||||
isThisReceiver: node.receiver is ThisExpression);
|
||||
|
||||
reportNonNullableInNullAwareWarningIfNeeded(
|
||||
readResult.inferredType, "??=", node.readOffset);
|
||||
@@ -4692,7 +4695,7 @@ class InferenceVisitor
|
||||
/// [typeContext] is used to create implicit generic tearoff instantiation
|
||||
/// if necessary. [isThisReceiver] must be set to `true` if the receiver is a
|
||||
/// `this` expression.
|
||||
PropertyGetInferenceResult _computePropertyGet(
|
||||
ExpressionInferenceResult _computePropertyGet(
|
||||
int fileOffset,
|
||||
Expression receiver,
|
||||
DartType receiverType,
|
||||
@@ -4876,11 +4879,12 @@ class InferenceVisitor
|
||||
read.fileOffset,
|
||||
propertyName.text.length,
|
||||
context: inferrer.getWhyNotPromotedContext(
|
||||
receiver,
|
||||
inferrer.flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
read,
|
||||
(type) => !type.isPotentiallyNullable));
|
||||
}
|
||||
return new PropertyGetInferenceResult(readResult, readTarget.member);
|
||||
return readResult;
|
||||
}
|
||||
|
||||
/// Creates a property set operation of [writeTarget] on [receiver] using
|
||||
@@ -5212,13 +5216,12 @@ class InferenceVisitor
|
||||
DartType nonNullReceiverType = receiverType.toNonNull();
|
||||
|
||||
ExpressionInferenceResult readResult = _computePropertyGet(
|
||||
node.readOffset,
|
||||
readReceiver,
|
||||
nonNullReceiverType,
|
||||
node.propertyName,
|
||||
const UnknownType(),
|
||||
isThisReceiver: node.receiver is ThisExpression)
|
||||
.expressionInferenceResult;
|
||||
node.readOffset,
|
||||
readReceiver,
|
||||
nonNullReceiverType,
|
||||
node.propertyName,
|
||||
const UnknownType(),
|
||||
isThisReceiver: node.receiver is ThisExpression);
|
||||
Expression read = readResult.expression;
|
||||
DartType readType = readResult.inferredType;
|
||||
|
||||
@@ -5749,9 +5752,8 @@ class InferenceVisitor
|
||||
DartType nonNullReceiverType = receiverType.toNonNull();
|
||||
|
||||
ExpressionInferenceResult readResult = _computePropertyGet(node.readOffset,
|
||||
readReceiver, nonNullReceiverType, node.name, typeContext,
|
||||
isThisReceiver: node.receiver is ThisExpression)
|
||||
.expressionInferenceResult;
|
||||
readReceiver, nonNullReceiverType, node.name, typeContext,
|
||||
isThisReceiver: node.receiver is ThisExpression);
|
||||
Expression read = readResult.expression;
|
||||
DartType readType = readResult.inferredType;
|
||||
inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
|
||||
@@ -5843,13 +5845,11 @@ class InferenceVisitor
|
||||
DartType receiverType = result.nullAwareActionType;
|
||||
|
||||
node.receiver = receiver..parent = node;
|
||||
PropertyGetInferenceResult propertyGetInferenceResult = _computePropertyGet(
|
||||
ExpressionInferenceResult readResult = _computePropertyGet(
|
||||
node.fileOffset, receiver, receiverType, node.name, typeContext,
|
||||
isThisReceiver: node.receiver is ThisExpression);
|
||||
ExpressionInferenceResult readResult =
|
||||
propertyGetInferenceResult.expressionInferenceResult;
|
||||
inferrer.flowAnalysis.propertyGet(node, node.receiver, node.name.text,
|
||||
propertyGetInferenceResult.member, readResult.inferredType);
|
||||
inferrer.flowAnalysis.propertyGet(
|
||||
node, node.receiver, node.name.text, readResult.inferredType);
|
||||
ExpressionInferenceResult expressionInferenceResult =
|
||||
inferrer.createNullAwareExpressionInferenceResult(
|
||||
readResult.inferredType, readResult.expression, nullAwareGuards);
|
||||
|
||||
@@ -290,13 +290,14 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
/// promoted, to be used when reporting an error for a larger expression
|
||||
/// containing [receiver]. [node] is the containing tree node.
|
||||
List<LocatedMessage> getWhyNotPromotedContext(
|
||||
Expression receiver,
|
||||
Map<DartType, NonPromotionReason> whyNotPromoted,
|
||||
TreeNode node,
|
||||
bool Function(DartType) typeFilter) {
|
||||
List<LocatedMessage> context;
|
||||
if (whyNotPromoted != null && whyNotPromoted.isNotEmpty) {
|
||||
_WhyNotPromotedVisitor whyNotPromotedVisitor =
|
||||
new _WhyNotPromotedVisitor(this);
|
||||
new _WhyNotPromotedVisitor(this, receiver);
|
||||
for (core.MapEntry<DartType, NonPromotionReason> entry
|
||||
in whyNotPromoted.entries) {
|
||||
if (!typeFilter(entry.key)) continue;
|
||||
@@ -614,6 +615,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
nullabilityErrorTemplate.withArguments(expressionType,
|
||||
declaredContextType ?? contextType, isNonNullableByDefault),
|
||||
context: getWhyNotPromotedContext(
|
||||
expression,
|
||||
flowAnalysis?.whyNotPromoted(expression)(),
|
||||
expression,
|
||||
(type) => typeSchemaEnvironment.isSubtypeOf(type,
|
||||
@@ -2824,6 +2826,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
// void Function() get call => () {};
|
||||
// }
|
||||
List<LocatedMessage> context = getWhyNotPromotedContext(
|
||||
receiver,
|
||||
flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
staticInvocation,
|
||||
(type) => !type.isPotentiallyNullable);
|
||||
@@ -2855,6 +2858,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
Expression replacement = result.applyResult(staticInvocation);
|
||||
if (!isTopLevel && target.isNullable) {
|
||||
List<LocatedMessage> context = getWhyNotPromotedContext(
|
||||
receiver,
|
||||
flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
staticInvocation,
|
||||
(type) => !type.isPotentiallyNullable);
|
||||
@@ -2968,6 +2972,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
Expression replacement = result.applyResult(expression);
|
||||
if (!isTopLevel && target.isNullableCallFunction) {
|
||||
List<LocatedMessage> context = getWhyNotPromotedContext(
|
||||
receiver,
|
||||
flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
expression,
|
||||
(type) => !type.isPotentiallyNullable);
|
||||
@@ -3142,6 +3147,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
replacement = result.applyResult(replacement);
|
||||
if (!isTopLevel && target.isNullable) {
|
||||
List<LocatedMessage> context = getWhyNotPromotedContext(
|
||||
receiver,
|
||||
flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
expression,
|
||||
(type) => !type.isPotentiallyNullable);
|
||||
@@ -3302,6 +3308,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
// void Function() get foo => () {};
|
||||
// }
|
||||
List<LocatedMessage> context = getWhyNotPromotedContext(
|
||||
receiver,
|
||||
flowAnalysis?.whyNotPromoted(receiver)(),
|
||||
invocationResult.expression,
|
||||
(type) => !type.isPotentiallyNullable);
|
||||
@@ -3458,8 +3465,8 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
new PropertyGet(originalReceiver, originalName, originalTarget)
|
||||
..fileOffset = fileOffset;
|
||||
}
|
||||
flowAnalysis.propertyGet(originalPropertyGet, originalReceiver,
|
||||
originalName.text, originalTarget, calleeType);
|
||||
flowAnalysis.propertyGet(
|
||||
originalPropertyGet, originalReceiver, originalName.text, calleeType);
|
||||
Expression propertyGet = originalPropertyGet;
|
||||
if (receiver is! ThisExpression &&
|
||||
calleeType is! DynamicType &&
|
||||
@@ -3511,8 +3518,11 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
// }
|
||||
// TODO(paulberry): would it be better to report NullableMethodCallError
|
||||
// in this scenario?
|
||||
List<LocatedMessage> context = getWhyNotPromotedContext(whyNotPromoted(),
|
||||
invocationResult.expression, (type) => !type.isPotentiallyNullable);
|
||||
List<LocatedMessage> context = getWhyNotPromotedContext(
|
||||
receiver,
|
||||
whyNotPromoted(),
|
||||
invocationResult.expression,
|
||||
(type) => !type.isPotentiallyNullable);
|
||||
invocationResult = wrapExpressionInferenceResultInProblem(
|
||||
invocationResult,
|
||||
templateNullableExpressionCallError.withArguments(
|
||||
@@ -3843,7 +3853,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
return instantiateTearOff(inferredType, typeContext, expression);
|
||||
}
|
||||
flowAnalysis.thisOrSuperPropertyGet(
|
||||
expression, expression.name.name, member, inferredType);
|
||||
expression, expression.name.name, inferredType);
|
||||
return new ExpressionInferenceResult(inferredType, expression);
|
||||
}
|
||||
|
||||
@@ -4634,17 +4644,6 @@ class WrapInProblemInferenceResult implements InvocationInferenceResult {
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of inference of a property get expression.
|
||||
class PropertyGetInferenceResult {
|
||||
/// The main inference result.
|
||||
final ExpressionInferenceResult expressionInferenceResult;
|
||||
|
||||
/// The property that was looked up, or `null` if no property was found.
|
||||
final Member member;
|
||||
|
||||
PropertyGetInferenceResult(this.expressionInferenceResult, this.member);
|
||||
}
|
||||
|
||||
/// The result of an expression inference.
|
||||
class ExpressionInferenceResult {
|
||||
/// The inferred type of the expression.
|
||||
@@ -5135,11 +5134,13 @@ class _WhyNotPromotedVisitor
|
||||
DartType> {
|
||||
final TypeInferrerImpl inferrer;
|
||||
|
||||
final Expression receiver;
|
||||
|
||||
Member propertyReference;
|
||||
|
||||
DartType propertyType;
|
||||
|
||||
_WhyNotPromotedVisitor(this.inferrer);
|
||||
_WhyNotPromotedVisitor(this.inferrer, this.receiver);
|
||||
|
||||
@override
|
||||
LocatedMessage visitDemoteViaExplicitWrite(
|
||||
@@ -5157,16 +5158,26 @@ class _WhyNotPromotedVisitor
|
||||
|
||||
@override
|
||||
LocatedMessage visitPropertyNotPromoted(PropertyNotPromoted reason) {
|
||||
Object member = reason.propertyMember;
|
||||
if (member is Member) {
|
||||
Member member;
|
||||
Expression receiver = this.receiver;
|
||||
if (receiver is InstanceGet) {
|
||||
member = receiver.interfaceTarget;
|
||||
} else if (receiver is SuperPropertyGet) {
|
||||
member = receiver.interfaceTarget;
|
||||
} else if (receiver is StaticInvocation) {
|
||||
member = receiver.target;
|
||||
} else if (receiver is PropertyGet) {
|
||||
member = receiver.interfaceTarget;
|
||||
} else {
|
||||
assert(false, 'Unrecognized receiver: ${receiver.runtimeType}');
|
||||
}
|
||||
if (member != null) {
|
||||
propertyReference = member;
|
||||
propertyType = reason.staticType;
|
||||
return templateFieldNotPromoted
|
||||
.withArguments(reason.propertyName, reason.documentationLink)
|
||||
.withLocation(member.fileUri, member.fileOffset, noLength);
|
||||
} else {
|
||||
assert(member == null,
|
||||
'Unrecognized property member: ${member.runtimeType}');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user