diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart index bf501a059c2..e4c7261dc57 100644 --- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart +++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart @@ -736,13 +736,8 @@ abstract class FlowAnalysis _wrapped.propertyGet( - wholeExpression, target, propertyName, propertyMember, staticType)); + wholeExpression, target, propertyName, staticType)); } @override @@ -1389,13 +1378,12 @@ class FlowAnalysisDebug _wrapped.thisOrSuperPropertyGet( - expression, propertyName, propertyMember, staticType)); + expression, propertyName, staticType)); } @override @@ -2346,17 +2334,12 @@ class PropertyNotPromoted 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 { /// Creates a reference representing a get of a property called [propertyName] /// on the reference represented by `this`. - Reference propertyGet( - String propertyName, Object? propertyMember) => - new _PropertyGetReference( - this, propertyName, propertyMember); + Reference propertyGet(String propertyName) => + new _PropertyGetReference(this, propertyName); /// Stores info for this reference in [variableInfo]. void storeInfo(Map> variableInfo, @@ -3971,14 +3952,14 @@ class _FlowAnalysisImpl? reference = _getExpressionReference(target)?.reference; if (reference != null) { _storeExpressionReference( wholeExpression, new ReferenceWithType( - reference.propertyGet(propertyName, propertyMember), staticType)); + reference.propertyGet(propertyName), staticType)); } } @@ -4035,13 +4016,12 @@ class _FlowAnalysisImpl( - new _ThisReference() - .propertyGet(propertyName, propertyMember), + new _ThisReference().propertyGet(propertyName), staticType)); } @@ -4706,7 +4686,7 @@ class _LegacyTypePromotion? ssaNodeForTesting(Variable variable) { @@ -4726,8 +4706,8 @@ class _LegacyTypePromotion /// 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 Function() getNonPromotionReasons( @@ -4945,8 +4920,7 @@ class _PropertyGetReference return () { Map result = {}; for (Type type in promotedTypes) { - result[type] = - new PropertyNotPromoted(propertyName, propertyMember, staticType); + result[type] = new PropertyNotPromoted(propertyName, staticType); } return result; }; diff --git a/pkg/_fe_analyzer_shared/test/mini_ast.dart b/pkg/_fe_analyzer_shared/test/mini_ast.dart index fd0db4bbbf3..5e41049c48b 100644 --- a/pkg/_fe_analyzer_shared/test/mini_ast.dart +++ b/pkg/_fe_analyzer_shared/test/mini_ast.dart @@ -1510,7 +1510,7 @@ class _Property extends LValue { Harness h, FlowAnalysis 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 flow) { - flow.thisOrSuperPropertyGet(this, propertyName, propertyName, type); + flow.thisOrSuperPropertyGet(this, propertyName, type); return type; } } diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart index 3b63d6ce608..aaaa1821017 100644 --- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart @@ -121,7 +121,8 @@ class AssignmentExpressionResolver { CompileTimeErrorCode.INVALID_ASSIGNMENT, right, [rightType, writeType], - _resolver.computeWhyNotPromotedMessages(right, whyNotPromoted?.call()), + _resolver.computeWhyNotPromotedMessages( + right, right, whyNotPromoted?.call()), ); } diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart index a6ab6e7bf85..caff68307d9 100644 --- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart @@ -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; } diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart index e2d53364994..8a6475857f0 100644 --- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart @@ -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); } diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart index 4ffbaaa8b07..cff8b7e4257 100644 --- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart @@ -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)()); } } diff --git a/pkg/analyzer/lib/src/error/bool_expression_verifier.dart b/pkg/analyzer/lib/src/error/bool_expression_verifier.dart index e56e3ad7d48..43d246299da 100644 --- a/pkg/analyzer/lib/src/error/bool_expression_verifier.dart +++ b/pkg/analyzer/lib/src/error/bool_expression_verifier.dart @@ -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); } diff --git a/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart b/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart index fb96d1b6712..cf1f3b53e1b 100644 --- a/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart +++ b/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart @@ -76,8 +76,8 @@ class NullableDereferenceVerifier { List? 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; diff --git a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart index ce693933d51..af745c8a6d8 100644 --- a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart +++ b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart @@ -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 computeWhyNotPromotedMessages( + Expression? expression, SyntacticEntity errorEntity, Map? whyNotPromoted); @@ -312,7 +313,8 @@ mixin ErrorDetectionHelpers { errorCode, getErrorNode(expression), [actualStaticType, expectedStaticType], - computeWhyNotPromotedMessages(expression, whyNotPromoted?.call()), + computeWhyNotPromotedMessages( + expression, expression, whyNotPromoted?.call()), ); return false; } diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 0d097e9a9ce..9601c2e9b08 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart @@ -312,6 +312,7 @@ class ErrorVerifier extends RecursiveAstVisitor @override List computeWhyNotPromotedMessages( + Expression? expression, SyntacticEntity errorEntity, Map? whyNotPromoted) { return []; diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index b8787935156..1a1918de1dd 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart @@ -533,13 +533,17 @@ class ResolverVisitor extends ScopedVisitor with ErrorDetectionHelpers { @override List computeWhyNotPromotedMessages( + Expression? expression, SyntacticEntity errorEntity, Map? whyNotPromoted) { + if (expression is NamedExpression) { + expression = expression.expression; + } List 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 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; diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart index 3458ef6436a..89fdd5e240b 100644 --- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart +++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart @@ -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); diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart index 463c05b653f..15606b8f539 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart @@ -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 getWhyNotPromotedContext( + Expression receiver, Map whyNotPromoted, TreeNode node, bool Function(DartType) typeFilter) { List context; if (whyNotPromoted != null && whyNotPromoted.isNotEmpty) { _WhyNotPromotedVisitor whyNotPromotedVisitor = - new _WhyNotPromotedVisitor(this); + new _WhyNotPromotedVisitor(this, receiver); for (core.MapEntry 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 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 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 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 context = getWhyNotPromotedContext( + receiver, flowAnalysis?.whyNotPromoted(receiver)(), expression, (type) => !type.isPotentiallyNullable); @@ -3302,6 +3308,7 @@ class TypeInferrerImpl implements TypeInferrer { // void Function() get foo => () {}; // } List 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 context = getWhyNotPromotedContext(whyNotPromoted(), - invocationResult.expression, (type) => !type.isPotentiallyNullable); + List 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; } }