mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:47:13 +00:00
[cfe] Pass return type as part of callee type for invocation inference
Change-Id: I3b2f54fe73cc7f7c427e51e20cb60b25fc45f6bc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/156885 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
56ba486709
commit
25e08663ce
|
@ -433,14 +433,12 @@ class InferenceVisitor
|
|||
inferrer.inferConstructorParameterTypes(node.target);
|
||||
bool hasExplicitTypeArguments =
|
||||
getExplicitTypeArguments(node.arguments) != null;
|
||||
InvocationInferenceResult result = inferrer.inferInvocation(
|
||||
typeContext,
|
||||
node.fileOffset,
|
||||
FunctionType functionType = replaceReturnType(
|
||||
node.target.function
|
||||
.computeThisFunctionType(inferrer.library.nonNullable),
|
||||
node.arguments,
|
||||
returnType:
|
||||
computeConstructorReturnType(node.target, inferrer.coreTypes),
|
||||
computeConstructorReturnType(node.target, inferrer.coreTypes));
|
||||
InvocationInferenceResult result = inferrer.inferInvocation(
|
||||
typeContext, node.fileOffset, functionType, node.arguments,
|
||||
isConst: node.isConst);
|
||||
if (!inferrer.isTopLevel) {
|
||||
SourceLibraryBuilder library = inferrer.library;
|
||||
|
@ -721,14 +719,14 @@ class InferenceVisitor
|
|||
FactoryConstructorInvocationJudgment node, DartType typeContext) {
|
||||
bool hadExplicitTypeArguments =
|
||||
getExplicitTypeArguments(node.arguments) != null;
|
||||
InvocationInferenceResult result = inferrer.inferInvocation(
|
||||
typeContext,
|
||||
node.fileOffset,
|
||||
|
||||
FunctionType functionType = replaceReturnType(
|
||||
node.target.function
|
||||
.computeThisFunctionType(inferrer.library.nonNullable),
|
||||
node.arguments,
|
||||
returnType:
|
||||
computeConstructorReturnType(node.target, inferrer.coreTypes),
|
||||
computeConstructorReturnType(node.target, inferrer.coreTypes));
|
||||
|
||||
InvocationInferenceResult result = inferrer.inferInvocation(
|
||||
typeContext, node.fileOffset, functionType, node.arguments,
|
||||
isConst: node.isConst);
|
||||
node.hasBeenInferred = true;
|
||||
Expression resultNode = node;
|
||||
|
@ -757,9 +755,10 @@ class InferenceVisitor
|
|||
FunctionType calleeType = node.target.function
|
||||
.computeAliasedConstructorFunctionType(
|
||||
typedef, inferrer.library.library);
|
||||
calleeType = replaceReturnType(calleeType, calleeType.returnType.unalias);
|
||||
InvocationInferenceResult result = inferrer.inferInvocation(
|
||||
typeContext, node.fileOffset, calleeType, node.arguments,
|
||||
returnType: calleeType.returnType.unalias, isConst: node.isConst);
|
||||
isConst: node.isConst);
|
||||
node.hasBeenInferred = true;
|
||||
Expression resultNode = node;
|
||||
if (!inferrer.isTopLevel) {
|
||||
|
@ -784,9 +783,10 @@ class InferenceVisitor
|
|||
Typedef typedef = node.typeAliasBuilder.typedef;
|
||||
FunctionType calleeType = node.target.function
|
||||
.computeAliasedFactoryFunctionType(typedef, inferrer.library.library);
|
||||
calleeType = replaceReturnType(calleeType, calleeType.returnType.unalias);
|
||||
InvocationInferenceResult result = inferrer.inferInvocation(
|
||||
typeContext, node.fileOffset, calleeType, node.arguments,
|
||||
returnType: calleeType.returnType.unalias, isConst: node.isConst);
|
||||
isConst: node.isConst);
|
||||
node.hasBeenInferred = true;
|
||||
Expression resultNode = node;
|
||||
if (!inferrer.isTopLevel) {
|
||||
|
@ -1133,14 +1133,13 @@ class InferenceVisitor
|
|||
Substitution substitution = Substitution.fromSupertype(
|
||||
inferrer.classHierarchy.getClassAsInstanceOf(
|
||||
inferrer.thisType.classNode, node.target.enclosingClass));
|
||||
inferrer.inferInvocation(
|
||||
null,
|
||||
node.fileOffset,
|
||||
FunctionType functionType = replaceReturnType(
|
||||
substitution.substituteType(node.target.function
|
||||
.computeThisFunctionType(inferrer.library.nonNullable)
|
||||
.withoutTypeParameters),
|
||||
node.argumentsJudgment,
|
||||
returnType: inferrer.thisType,
|
||||
inferrer.thisType);
|
||||
inferrer.inferInvocation(
|
||||
null, node.fileOffset, functionType, node.argumentsJudgment,
|
||||
skipTypeArgumentInference: true);
|
||||
}
|
||||
|
||||
|
@ -5013,14 +5012,13 @@ class InferenceVisitor
|
|||
classTypeParameters[i], inferrer.library.library);
|
||||
}
|
||||
ArgumentsImpl.setNonInferrableArgumentTypes(node.arguments, typeArguments);
|
||||
inferrer.inferInvocation(
|
||||
null,
|
||||
node.fileOffset,
|
||||
FunctionType functionType = replaceReturnType(
|
||||
node.target.function
|
||||
.computeThisFunctionType(inferrer.library.nonNullable),
|
||||
node.arguments,
|
||||
returnType: inferrer.coreTypes.thisInterfaceType(
|
||||
node.target.enclosingClass, inferrer.library.nonNullable),
|
||||
inferrer.coreTypes.thisInterfaceType(
|
||||
node.target.enclosingClass, inferrer.library.nonNullable));
|
||||
inferrer.inferInvocation(
|
||||
null, node.fileOffset, functionType, node.arguments,
|
||||
skipTypeArgumentInference: true);
|
||||
ArgumentsImpl.removeNonInferrableArgumentTypes(node.arguments);
|
||||
}
|
||||
|
@ -5225,14 +5223,13 @@ class InferenceVisitor
|
|||
Substitution substitution = Substitution.fromSupertype(
|
||||
inferrer.classHierarchy.getClassAsInstanceOf(
|
||||
inferrer.thisType.classNode, node.target.enclosingClass));
|
||||
inferrer.inferInvocation(
|
||||
null,
|
||||
node.fileOffset,
|
||||
FunctionType functionType = replaceReturnType(
|
||||
substitution.substituteType(node.target.function
|
||||
.computeThisFunctionType(inferrer.library.nonNullable)
|
||||
.withoutTypeParameters),
|
||||
node.arguments,
|
||||
returnType: inferrer.thisType,
|
||||
inferrer.thisType);
|
||||
inferrer.inferInvocation(
|
||||
null, node.fileOffset, functionType, node.arguments,
|
||||
skipTypeArgumentInference: true);
|
||||
}
|
||||
|
||||
|
|
|
@ -218,14 +218,6 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
/// inside a closure.
|
||||
ClosureContext closureContext;
|
||||
|
||||
/// The [Substitution] inferred by the last [inferInvocation], or `null` if
|
||||
/// the last invocation didn't require any inference.
|
||||
Substitution lastInferredSubstitution;
|
||||
|
||||
/// The [FunctionType] of the callee in the last [inferInvocation], or `null`
|
||||
/// if the last invocation didn't require any inference.
|
||||
FunctionType lastCalleeType;
|
||||
|
||||
TypeInferrerImpl(this.engine, this.uriForInstrumentation, bool topLevel,
|
||||
this.thisType, this.library, this.assignedVariables, this.dataForTesting)
|
||||
: assert(library != null),
|
||||
|
@ -1653,20 +1645,13 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
{List<VariableDeclaration> hoistedExpressions,
|
||||
bool isSpecialCasedBinaryOperator: false,
|
||||
bool isSpecialCasedTernaryOperator: false,
|
||||
DartType returnType,
|
||||
DartType receiverType,
|
||||
bool skipTypeArgumentInference: false,
|
||||
bool isConst: false,
|
||||
bool isImplicitExtensionMember: false,
|
||||
bool isImplicitCall: false}) {
|
||||
assert(
|
||||
returnType == null || !containsFreeFunctionTypeVariables(returnType),
|
||||
"Return type $returnType contains free variables."
|
||||
"Provided function type: $calleeType.");
|
||||
int extensionTypeParameterCount = getExtensionTypeParameterCount(arguments);
|
||||
if (extensionTypeParameterCount != 0) {
|
||||
assert(returnType == null,
|
||||
"Unexpected explicit return type for extension method invocation.");
|
||||
return _inferGenericExtensionMethodInvocation(extensionTypeParameterCount,
|
||||
typeContext, offset, calleeType, arguments, hoistedExpressions,
|
||||
isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
|
||||
|
@ -1681,7 +1666,6 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
|
||||
isSpecialCasedTernaryOperator: isSpecialCasedTernaryOperator,
|
||||
receiverType: receiverType,
|
||||
returnType: returnType,
|
||||
skipTypeArgumentInference: skipTypeArgumentInference,
|
||||
isConst: isConst,
|
||||
isImplicitExtensionMember: isImplicitExtensionMember,
|
||||
|
@ -1770,17 +1754,10 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
{bool isSpecialCasedBinaryOperator: false,
|
||||
bool isSpecialCasedTernaryOperator: false,
|
||||
DartType receiverType,
|
||||
DartType returnType,
|
||||
bool skipTypeArgumentInference: false,
|
||||
bool isConst: false,
|
||||
bool isImplicitExtensionMember: false,
|
||||
bool isImplicitCall}) {
|
||||
assert(
|
||||
returnType == null || !containsFreeFunctionTypeVariables(returnType),
|
||||
"Return type $returnType contains free variables."
|
||||
"Provided function type: $calleeType.");
|
||||
lastInferredSubstitution = null;
|
||||
lastCalleeType = null;
|
||||
List<TypeParameter> calleeTypeParameters = calleeType.typeParameters;
|
||||
if (calleeTypeParameters.isNotEmpty) {
|
||||
// It's possible that one of the callee type parameters might match a type
|
||||
|
@ -1794,9 +1771,6 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
// in which me must do this, to avoid a performance regression?
|
||||
FreshTypeParameters fresh = getFreshTypeParameters(calleeTypeParameters);
|
||||
calleeType = fresh.applyToFunctionType(calleeType);
|
||||
if (returnType != null) {
|
||||
returnType = fresh.substitute(returnType);
|
||||
}
|
||||
calleeTypeParameters = fresh.freshTypeParameters;
|
||||
}
|
||||
List<DartType> explicitTypeArguments = getExplicitTypeArguments(arguments);
|
||||
|
@ -1825,8 +1799,8 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
calleeTypeParameters.length, const UnknownType());
|
||||
typeSchemaEnvironment.inferGenericFunctionOrType(
|
||||
isNonNullableByDefault
|
||||
? returnType ?? calleeType.returnType
|
||||
: legacyErasure(coreTypes, returnType ?? calleeType.returnType),
|
||||
? calleeType.returnType
|
||||
: legacyErasure(coreTypes, calleeType.returnType),
|
||||
calleeTypeParameters,
|
||||
null,
|
||||
null,
|
||||
|
@ -1893,12 +1867,16 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
}
|
||||
}
|
||||
if (isSpecialCasedBinaryOperator) {
|
||||
returnType = typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
|
||||
receiverType, actualTypes[0],
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
calleeType = replaceReturnType(
|
||||
calleeType,
|
||||
typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
|
||||
receiverType, actualTypes[0],
|
||||
isNonNullableByDefault: isNonNullableByDefault));
|
||||
} else if (isSpecialCasedTernaryOperator) {
|
||||
returnType = typeSchemaEnvironment.getTypeOfSpecialCasedTernaryOperator(
|
||||
receiverType, actualTypes[0], actualTypes[1], library.library);
|
||||
calleeType = replaceReturnType(
|
||||
calleeType,
|
||||
typeSchemaEnvironment.getTypeOfSpecialCasedTernaryOperator(
|
||||
receiverType, actualTypes[0], actualTypes[1], library.library));
|
||||
}
|
||||
for (NamedExpression namedArgument in arguments.named) {
|
||||
DartType formalType =
|
||||
|
@ -1968,7 +1946,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
|
||||
if (inferenceNeeded) {
|
||||
typeSchemaEnvironment.inferGenericFunctionOrType(
|
||||
returnType ?? calleeType.returnType,
|
||||
calleeType.returnType,
|
||||
calleeTypeParameters,
|
||||
formalTypes,
|
||||
actualTypes,
|
||||
|
@ -2034,19 +2012,11 @@ class TypeInferrerImpl implements TypeInferrer {
|
|||
}
|
||||
}
|
||||
DartType inferredType;
|
||||
lastInferredSubstitution = substitution;
|
||||
lastCalleeType = calleeType;
|
||||
if (returnType != null) {
|
||||
inferredType = substitution == null
|
||||
? returnType
|
||||
: substitution.substituteType(returnType);
|
||||
} else {
|
||||
if (substitution != null) {
|
||||
calleeType =
|
||||
substitution.substituteType(calleeType.withoutTypeParameters);
|
||||
}
|
||||
inferredType = calleeType.returnType;
|
||||
if (substitution != null) {
|
||||
calleeType =
|
||||
substitution.substituteType(calleeType.withoutTypeParameters);
|
||||
}
|
||||
inferredType = calleeType.returnType;
|
||||
assert(
|
||||
!containsFreeFunctionTypeVariables(inferredType),
|
||||
"Inferred return type $inferredType contains free variables."
|
||||
|
@ -4227,3 +4197,11 @@ class TypedTearoff {
|
|||
|
||||
TypedTearoff(this.tearoffType, this.tearoff);
|
||||
}
|
||||
|
||||
FunctionType replaceReturnType(FunctionType functionType, DartType returnType) {
|
||||
return new FunctionType(functionType.positionalParameters, returnType,
|
||||
functionType.declaredNullability,
|
||||
requiredParameterCount: functionType.requiredParameterCount,
|
||||
namedParameters: functionType.namedParameters,
|
||||
typeParameters: functionType.typeParameters);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue