Skip to content

Commit e5a587f

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Add helper for creating property get during inference
Change-Id: Ic4b8f78cc0ced98f17d2dc27c2d4a6d6e273af91 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122389 Reviewed-by: Aske Simon Christensen <askesc@google.com>
1 parent 857502b commit e5a587f

File tree

3 files changed

+134
-190
lines changed

3 files changed

+134
-190
lines changed

pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart

Lines changed: 133 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -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

pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import '../fasta_codes.dart'
5656
templateSpreadTypeMismatch,
5757
templateSuperclassHasNoMethod,
5858
templateSwitchExpressionNotAssignable,
59+
templateUndefinedGetter,
5960
templateUndefinedMethod,
6061
templateUndefinedSetter,
6162
templateWebLiteralCannotBeRepresentedExactly;

0 commit comments

Comments
 (0)