@@ -2916,7 +2916,8 @@ class InferenceVisitor
29162916 Expression binary;
29172917 if (binaryTarget.isMissing) {
29182918 binary = inferrer.helper.buildProblem (
2919- templateUndefinedMethod.withArguments (binaryName.name, leftType),
2919+ templateUndefinedMethod.withArguments (
2920+ binaryName.name, inferrer.resolveTypeParameter (leftType)),
29202921 fileOffset,
29212922 binaryName.name.length);
29222923 } else if (binaryTarget.isExtensionMember) {
@@ -2974,7 +2975,7 @@ class InferenceVisitor
29742975 if (readTarget.isMissing) {
29752976 read = inferrer.helper.buildProblem (
29762977 templateUndefinedMethod.withArguments (
2977- indexGetName.name, receiverType),
2978+ indexGetName.name, inferrer. resolveTypeParameter ( receiverType) ),
29782979 fileOffset,
29792980 noLength);
29802981 } else if (readTarget.isExtensionMember) {
@@ -3029,7 +3030,7 @@ class InferenceVisitor
30293030 if (writeTarget.isMissing) {
30303031 write = inferrer.helper.buildProblem (
30313032 templateUndefinedMethod.withArguments (
3032- indexSetName.name, receiverType),
3033+ indexSetName.name, inferrer. resolveTypeParameter ( receiverType) ),
30333034 fileOffset,
30343035 noLength);
30353036 } else if (writeTarget.isExtensionMember) {
@@ -3051,6 +3052,108 @@ class InferenceVisitor
30513052 return write;
30523053 }
30533054
3055+ /// Creates a property get of [propertyName] on [receiver] of type
3056+ /// [receiverType] .
3057+ ///
3058+ /// [fileOffset] is used as the file offset for created nodes. [receiverType]
3059+ /// is the already inferred type of the [receiver] expression. The
3060+ /// [typeContext] is used to create implicit generic tearoff instantiation
3061+ /// if necessary. [isThisReceiver] must be set to `true` if the receiver is a
3062+ /// `this` expression.
3063+ ExpressionInferenceResult _computePropertyGet (
3064+ int fileOffset,
3065+ Expression receiver,
3066+ DartType receiverType,
3067+ Name propertyName,
3068+ DartType typeContext,
3069+ {bool isThisReceiver}) {
3070+ assert (isThisReceiver != null );
3071+
3072+ ObjectAccessTarget readTarget = inferrer.findInterfaceMember (
3073+ receiverType, propertyName, fileOffset,
3074+ includeExtensionMethods: true );
3075+
3076+ DartType readType = inferrer.getGetterType (readTarget, receiverType);
3077+
3078+ Expression read;
3079+ if (readTarget.isMissing) {
3080+ read = inferrer.helper.buildProblem (
3081+ templateUndefinedGetter.withArguments (
3082+ propertyName.name, inferrer.resolveTypeParameter (receiverType)),
3083+ fileOffset,
3084+ propertyName.name.length);
3085+ } else if (readTarget.isExtensionMember) {
3086+ switch (readTarget.extensionMethodKind) {
3087+ case ProcedureKind .Getter :
3088+ read = new StaticInvocation (
3089+ readTarget.member,
3090+ new Arguments (< Expression > [
3091+ receiver,
3092+ ], types: readTarget.inferredExtensionTypeArguments)
3093+ ..fileOffset = fileOffset)
3094+ ..fileOffset = fileOffset;
3095+ break ;
3096+ case ProcedureKind .Method :
3097+ read = new StaticInvocation (
3098+ readTarget.tearoffTarget,
3099+ new Arguments (< Expression > [
3100+ receiver,
3101+ ], types: readTarget.inferredExtensionTypeArguments)
3102+ ..fileOffset = fileOffset)
3103+ ..fileOffset = fileOffset;
3104+ return inferrer.instantiateTearOff (readType, typeContext, read);
3105+ case ProcedureKind .Setter :
3106+ case ProcedureKind .Factory :
3107+ case ProcedureKind .Operator :
3108+ unhandled ('$readTarget ' , "inferPropertyGet" , null , null );
3109+ break ;
3110+ }
3111+ } else {
3112+ if (readTarget.isInstanceMember &&
3113+ inferrer.instrumentation != null &&
3114+ receiverType == const DynamicType ()) {
3115+ inferrer.instrumentation.record (
3116+ inferrer.uriForInstrumentation,
3117+ fileOffset,
3118+ 'target' ,
3119+ new InstrumentationValueForMember (readTarget.member));
3120+ }
3121+ read = new PropertyGet (receiver, propertyName, readTarget.member)
3122+ ..fileOffset = fileOffset;
3123+ bool checkReturn = false ;
3124+ if (readTarget.isInstanceMember && ! isThisReceiver) {
3125+ Member interfaceMember = readTarget.member;
3126+ if (interfaceMember is Procedure ) {
3127+ checkReturn =
3128+ TypeInferrerImpl .returnedTypeParametersOccurNonCovariantly (
3129+ interfaceMember.enclosingClass,
3130+ interfaceMember.function.returnType);
3131+ } else if (interfaceMember is Field ) {
3132+ checkReturn =
3133+ TypeInferrerImpl .returnedTypeParametersOccurNonCovariantly (
3134+ interfaceMember.enclosingClass, interfaceMember.type);
3135+ }
3136+ }
3137+ if (checkReturn) {
3138+ if (inferrer.instrumentation != null ) {
3139+ inferrer.instrumentation.record (
3140+ inferrer.uriForInstrumentation,
3141+ fileOffset,
3142+ 'checkReturn' ,
3143+ new InstrumentationValueForType (readType));
3144+ }
3145+ read = new AsExpression (read, readType)
3146+ ..isTypeError = true
3147+ ..fileOffset = fileOffset;
3148+ }
3149+ Member member = readTarget.member;
3150+ if (member is Procedure && member.kind == ProcedureKind .Method ) {
3151+ return inferrer.instantiateTearOff (readType, typeContext, read);
3152+ }
3153+ }
3154+ return new ExpressionInferenceResult (readType, read);
3155+ }
3156+
30543157 ExpressionInferenceResult visitCompoundIndexSet (
30553158 CompoundIndexSet node, DartType typeContext) {
30563159 ExpressionInferenceResult receiverResult = inferrer.inferExpression (
@@ -3216,47 +3319,11 @@ class InferenceVisitor
32163319 .findInterfaceMember (receiverType, equalsName, node.receiver.fileOffset)
32173320 .member;
32183321
3219- ObjectAccessTarget readTarget = inferrer.findInterfaceMember (
3220- receiverType, node.propertyName, node.readOffset,
3221- includeExtensionMethods: true );
3222-
3223- MethodContravarianceCheckKind readCheckKind =
3224- inferrer.preCheckInvocationContravariance (receiverType, readTarget,
3225- isThisReceiver: node.receiver is ThisExpression );
3226-
3227- DartType readType = inferrer.getGetterType (readTarget, receiverType);
3228-
3229- Expression read;
3230- if (readTarget.isMissing) {
3231- read = inferrer.helper.buildProblem (
3232- templateUndefinedMethod.withArguments (
3233- node.propertyName.name, receiverType),
3234- node.readOffset,
3235- node.propertyName.name.length);
3236- } else if (readTarget.isExtensionMember) {
3237- read = new StaticInvocation (
3238- readTarget.member,
3239- new Arguments (< Expression > [
3240- readReceiver,
3241- ], types: readTarget.inferredExtensionTypeArguments)
3242- ..fileOffset = node.readOffset)
3243- ..fileOffset = node.readOffset;
3244- } else {
3245- read = new PropertyGet (readReceiver, node.propertyName, readTarget.member)
3246- ..fileOffset = node.readOffset;
3247- if (readCheckKind == MethodContravarianceCheckKind .checkMethodReturn) {
3248- if (inferrer.instrumentation != null ) {
3249- inferrer.instrumentation.record (
3250- inferrer.uriForInstrumentation,
3251- node.readOffset,
3252- 'checkReturn' ,
3253- new InstrumentationValueForType (readType));
3254- }
3255- read = new AsExpression (read, readType)
3256- ..isTypeError = true
3257- ..fileOffset = node.readOffset;
3258- }
3259- }
3322+ ExpressionInferenceResult readResult = _computePropertyGet (node.readOffset,
3323+ readReceiver, receiverType, node.propertyName, const UnknownType (),
3324+ isThisReceiver: node.receiver is ThisExpression );
3325+ Expression read = readResult.expression;
3326+ DartType readType = readResult.inferredType;
32603327
32613328 VariableDeclaration leftVariable;
32623329 Expression left;
@@ -3797,51 +3864,16 @@ class InferenceVisitor
37973864 .findInterfaceMember (receiverType, equalsName, node.receiver.fileOffset)
37983865 .member;
37993866
3800- ObjectAccessTarget readTarget = inferrer.findInterfaceMember (
3801- receiverType, node.name, node.readOffset,
3802- includeExtensionMethods: true );
3803-
3804- MethodContravarianceCheckKind readCheckKind =
3805- inferrer.preCheckInvocationContravariance (receiverType, readTarget,
3806- isThisReceiver: node.receiver is ThisExpression );
3807-
3808- DartType readType = inferrer.getGetterType (readTarget, receiverType);
3867+ ExpressionInferenceResult readResult = _computePropertyGet (
3868+ node.readOffset, readReceiver, receiverType, node.name, typeContext,
3869+ isThisReceiver: node.receiver is ThisExpression );
3870+ Expression read = readResult.expression;
3871+ DartType readType = readResult.inferredType;
38093872
38103873 Member readEqualsMember = inferrer
38113874 .findInterfaceMember (readType, equalsName, node.testOffset)
38123875 .member;
38133876
3814- Expression read;
3815- if (readTarget.isMissing) {
3816- read = inferrer.helper.buildProblem (
3817- templateUndefinedMethod.withArguments (node.name.name, receiverType),
3818- node.readOffset,
3819- node.name.name.length);
3820- } else if (readTarget.isExtensionMember) {
3821- read = new StaticInvocation (
3822- readTarget.member,
3823- new Arguments (< Expression > [
3824- readReceiver,
3825- ], types: readTarget.inferredExtensionTypeArguments)
3826- ..fileOffset = node.readOffset)
3827- ..fileOffset = node.readOffset;
3828- } else {
3829- read = new PropertyGet (readReceiver, node.name, readTarget.member)
3830- ..fileOffset = node.readOffset;
3831- if (readCheckKind == MethodContravarianceCheckKind .checkMethodReturn) {
3832- if (inferrer.instrumentation != null ) {
3833- inferrer.instrumentation.record (
3834- inferrer.uriForInstrumentation,
3835- node.readOffset,
3836- 'checkReturn' ,
3837- new InstrumentationValueForType (readType));
3838- }
3839- read = new AsExpression (read, readType)
3840- ..isTypeError = true
3841- ..fileOffset = node.readOffset;
3842- }
3843- }
3844-
38453877 VariableDeclaration readVariable;
38463878 if (! node.forEffect) {
38473879 readVariable = createVariable (read, readType);
@@ -3960,7 +3992,23 @@ class InferenceVisitor
39603992 @override
39613993 ExpressionInferenceResult visitPropertyGet (
39623994 PropertyGet node, DartType typeContext) {
3963- return inferrer.inferPropertyGet (node, typeContext);
3995+ ExpressionInferenceResult result =
3996+ inferrer.inferExpression (node.receiver, const UnknownType (), true );
3997+ NullAwareGuard nullAwareGuard;
3998+ Expression receiver;
3999+ if (inferrer.isNonNullableByDefault) {
4000+ nullAwareGuard = result.nullAwareGuard;
4001+ receiver = result.nullAwareAction;
4002+ } else {
4003+ receiver = result.expression;
4004+ }
4005+ node.receiver = receiver..parent = node;
4006+ DartType receiverType = result.inferredType;
4007+ ExpressionInferenceResult readResult = _computePropertyGet (
4008+ node.fileOffset, receiver, receiverType, node.name, typeContext,
4009+ isThisReceiver: node.receiver is ThisExpression );
4010+ return new ExpressionInferenceResult .nullAware (
4011+ readResult.inferredType, readResult.expression, nullAwareGuard);
39644012 }
39654013
39664014 @override
0 commit comments