Fix type inference for function expression parameters

This commit is contained in:
Stanislav Erokhin
2015-03-05 20:45:26 +03:00
parent af4aff38e5
commit 8accdcc5cb
9 changed files with 76 additions and 18 deletions
@@ -410,6 +410,14 @@ public class JetPsiUtil {
return element instanceof JetSimpleNameExpression && isBackingFieldReference((JetSimpleNameExpression)element);
}
@Nullable
public static JetElement getExpressionOrLastStatementInBlock(@Nullable JetExpression expression) {
if (expression instanceof JetBlockExpression) {
return getLastStatementInABlock((JetBlockExpression) expression);
}
return expression;
}
@Nullable
public static JetElement getLastStatementInABlock(@Nullable JetBlockExpression blockExpression) {
if (blockExpression == null) return null;
@@ -136,7 +136,7 @@ public class ArgumentTypeResolver {
}
@NotNull
public static JetFunctionLiteralExpression getFunctionLiteralArgument(
public static JetFunction getFunctionLiteralArgument(
@NotNull JetExpression expression, @NotNull ResolutionContext context
) {
assert isFunctionLiteralArgument(expression, context);
@@ -145,12 +145,15 @@ public class ArgumentTypeResolver {
}
@Nullable
private static JetFunctionLiteralExpression getFunctionLiteralArgumentIfAny(
private static JetFunction getFunctionLiteralArgumentIfAny(
@NotNull JetExpression expression, @NotNull ResolutionContext context
) {
JetExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context);
if (deparenthesizedExpression instanceof JetFunctionLiteralExpression) {
return (JetFunctionLiteralExpression) deparenthesizedExpression;
return ((JetFunctionLiteralExpression) deparenthesizedExpression).getFunctionLiteral();
}
if (deparenthesizedExpression instanceof JetFunction) {
return (JetFunction) deparenthesizedExpression;
}
return null;
}
@@ -199,12 +202,12 @@ public class ArgumentTypeResolver {
@NotNull
public JetTypeInfo getFunctionLiteralTypeInfo(
@NotNull JetExpression expression,
@NotNull JetFunctionLiteralExpression functionLiteralExpression,
@NotNull JetFunction functionLiteral,
@NotNull CallResolutionContext<?> context,
@NotNull ResolveArgumentsMode resolveArgumentsMode
) {
if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
JetType type = getShapeTypeOfFunctionLiteral(functionLiteralExpression, context.scope, context.trace, true);
JetType type = getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, true);
return JetTypeInfo.create(type, context.dataFlowInfo);
}
return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
@@ -212,28 +215,27 @@ public class ArgumentTypeResolver {
@Nullable
public JetType getShapeTypeOfFunctionLiteral(
@NotNull JetFunctionLiteralExpression expression,
@NotNull JetFunction functionLiteral,
@NotNull JetScope scope,
@NotNull BindingTrace trace,
boolean expectedTypeIsUnknown
) {
if (expression.getFunctionLiteral().getValueParameterList() == null) {
if (functionLiteral.getValueParameterList() == null) {
return expectedTypeIsUnknown ? PLACEHOLDER_FUNCTION_TYPE : builtIns.getFunctionType(
Annotations.EMPTY, null, Collections.<JetType>emptyList(), DONT_CARE);
}
List<JetParameter> valueParameters = expression.getValueParameters();
List<JetParameter> valueParameters = functionLiteral.getValueParameters();
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
trace, "trace to resolve function literal parameter types");
List<JetType> parameterTypes = Lists.newArrayList();
for (JetParameter parameter : valueParameters) {
parameterTypes.add(resolveTypeRefWithDefault(parameter.getTypeReference(), scope, temporaryTrace, DONT_CARE));
}
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
JetType returnType = resolveTypeRefWithDefault(functionLiteral.getTypeReference(), scope, temporaryTrace, DONT_CARE);
assert returnType != null;
JetType receiverType = resolveTypeRefWithDefault(functionLiteral.getReceiverTypeReference(), scope, temporaryTrace, null);
return builtIns.getFunctionType(Annotations.EMPTY, receiverType, parameterTypes,
returnType);
returnType);
}
@Nullable
@@ -281,12 +281,12 @@ public class CandidateResolver {
if (argumentExpression == null) return;
if (!ArgumentTypeResolver.isFunctionLiteralArgument(argumentExpression, context)) return;
JetFunctionLiteralExpression functionLiteralExpression = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression, context);
JetFunction functionLiteral = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression, context);
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT);
if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) {
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteralExpression, context.scope, context.trace, false);
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false);
}
if (expectedType == null || !KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)
|| CallResolverUtil.hasUnknownFunctionParameter(expectedType)) {
@@ -301,7 +301,7 @@ public class CandidateResolver {
TemporaryTraceAndCache temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create(
context, "trace to resolve function literal with expected return type", argumentExpression);
JetElement statementExpression = JetPsiUtil.getLastStatementInABlock(functionLiteralExpression.getBodyExpression());
JetElement statementExpression = JetPsiUtil.getExpressionOrLastStatementInBlock(functionLiteral.getBodyExpression());
if (statementExpression == null) return;
boolean[] mismatch = new boolean[1];
ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
@@ -311,7 +311,7 @@ public class CandidateResolver {
.replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache)
.replaceContextDependency(INDEPENDENT);
JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(
argumentExpression, functionLiteralExpression, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType();
argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType();
if (!mismatch[0]) {
constraintSystem.addSubtypeConstraint(
type, effectiveExpectedType, VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex()));
@@ -323,7 +323,7 @@ public class CandidateResolver {
CallCandidateResolutionContext<D> newContext = context
.replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
.replaceContextDependency(INDEPENDENT);
JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteralExpression, newContext,
JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext,
RESOLVE_FUNCTION_ARGUMENTS).getType();
constraintSystem.addSubtypeConstraint(
type, effectiveExpectedType, VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex()));