resolve function literal expression (as parameter) after resolve call
(therefore only once) while resolve use FAKE_FUNCTION_TYPE as type for function literal (which is a subtype/supertype for any function type)
This commit is contained in:
+140
-8
@@ -16,22 +16,43 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeProjection;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||
import org.jetbrains.jet.lang.psi.ValueArgument;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.TypeResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.*;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveMode.RESOLVE_FUNCTION_ARGUMENTS;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveMode.SKIP_FUNCTION_ARGUMENTS;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
public class ArgumentTypeResolver {
|
||||
@NotNull
|
||||
private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
|
||||
|
||||
@NotNull
|
||||
private TypeResolver typeResolver;
|
||||
@NotNull
|
||||
@@ -47,16 +68,34 @@ public class ArgumentTypeResolver {
|
||||
this.expressionTypingServices = expressionTypingServices;
|
||||
}
|
||||
|
||||
public boolean isSubtypeOfForArgumentType(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
if (subtype == PLACEHOLDER_FUNCTION_TYPE) {
|
||||
return isFunctionOrErrorType(supertype) || KotlinBuiltIns.getInstance().isAny(supertype); //todo function type extends
|
||||
}
|
||||
if (supertype == PLACEHOLDER_FUNCTION_TYPE) {
|
||||
return isFunctionOrErrorType(subtype); //todo extends function type
|
||||
}
|
||||
return typeChecker.isSubtypeOf(subtype, supertype);
|
||||
}
|
||||
|
||||
private static boolean isFunctionOrErrorType(@NotNull JetType supertype) {
|
||||
return KotlinBuiltIns.getInstance().isFunctionType(supertype) || ErrorUtils.isErrorType(supertype);
|
||||
}
|
||||
|
||||
public void checkTypesWithNoCallee(@NotNull ResolutionContext context) {
|
||||
checkTypesWithNoCallee(context, SKIP_FUNCTION_ARGUMENTS);
|
||||
}
|
||||
|
||||
public void checkTypesWithNoCallee(@NotNull ResolutionContext context, @NotNull ResolveMode resolveFunctionArgumentBodies) {
|
||||
for (ValueArgument valueArgument : context.call.getValueArguments()) {
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
if (argumentExpression != null) {
|
||||
if (argumentExpression != null && !(argumentExpression instanceof JetFunctionLiteralExpression)) {
|
||||
expressionTypingServices.getType(context.scope, argumentExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
}
|
||||
}
|
||||
|
||||
for (JetExpression expression : context.call.getFunctionLiteralArguments()) {
|
||||
expressionTypingServices.getType(context.scope, expression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
if (resolveFunctionArgumentBodies == RESOLVE_FUNCTION_ARGUMENTS) {
|
||||
checkTypesForFunctionArgumentsWithNoCallee(context);
|
||||
}
|
||||
|
||||
for (JetTypeProjection typeProjection : context.call.getTypeArguments()) {
|
||||
@@ -70,6 +109,19 @@ public class ArgumentTypeResolver {
|
||||
}
|
||||
}
|
||||
|
||||
public void checkTypesForFunctionArgumentsWithNoCallee(@NotNull ResolutionContext context) {
|
||||
for (ValueArgument valueArgument : context.call.getValueArguments()) {
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
if (argumentExpression != null && (argumentExpression instanceof JetFunctionLiteralExpression)) {
|
||||
expressionTypingServices.getType(context.scope, argumentExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
}
|
||||
}
|
||||
|
||||
for (JetExpression expression : context.call.getFunctionLiteralArguments()) {
|
||||
expressionTypingServices.getType(context.scope, expression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkUnmappedArgumentTypes(ResolutionContext context, Set<ValueArgument> unmappedArguments) {
|
||||
for (ValueArgument valueArgument : unmappedArguments) {
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
@@ -78,4 +130,84 @@ public class ArgumentTypeResolver {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <D extends CallableDescriptor> void checkTypesForFunctionArguments(ResolutionContext context, ResolvedCallImpl<D> resolvedCall) {
|
||||
Map<ValueParameterDescriptor, ResolvedValueArgument> arguments = resolvedCall.getValueArguments();
|
||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : arguments.entrySet()) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
|
||||
JetType varargElementType = valueParameterDescriptor.getVarargElementType();
|
||||
JetType functionType;
|
||||
if (varargElementType != null) {
|
||||
functionType = varargElementType;
|
||||
}
|
||||
else {
|
||||
functionType = valueParameterDescriptor.getType();
|
||||
}
|
||||
ResolvedValueArgument valueArgument = entry.getValue();
|
||||
List<ValueArgument> valueArguments = valueArgument.getArguments();
|
||||
for (ValueArgument argument : valueArguments) {
|
||||
JetExpression expression = argument.getArgumentExpression();
|
||||
if (expression instanceof JetFunctionLiteralExpression) {
|
||||
expressionTypingServices.getType(context.scope, expression, functionType, context.dataFlowInfo, context.trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetTypeInfo getArgumentTypeInfo(
|
||||
@Nullable JetExpression expression,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull ResolveMode resolveFunctionArgumentBodies
|
||||
) {
|
||||
if (expression == null) {
|
||||
return JetTypeInfo.create(null, dataFlowInfo);
|
||||
}
|
||||
if (expression instanceof JetFunctionLiteralExpression && resolveFunctionArgumentBodies == SKIP_FUNCTION_ARGUMENTS) {
|
||||
JetType type = getFunctionLiteralType((JetFunctionLiteralExpression) expression, scope, trace);
|
||||
return JetTypeInfo.create(type, dataFlowInfo);
|
||||
}
|
||||
return expressionTypingServices.getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetType getFunctionLiteralType(
|
||||
@NotNull JetFunctionLiteralExpression expression,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
List<JetParameter> valueParameters = expression.getValueParameters();
|
||||
if (valueParameters.isEmpty()) {
|
||||
return PLACEHOLDER_FUNCTION_TYPE;
|
||||
}
|
||||
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,
|
||||
PLACEHOLDER_FUNCTION_PARAMETER_TYPE));
|
||||
}
|
||||
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
||||
JetType returnType = resolveTypeRefWithDefault(functionLiteral.getReturnTypeRef(), scope, temporaryTrace,
|
||||
PLACEHOLDER_FUNCTION_PARAMETER_TYPE);
|
||||
assert returnType != null;
|
||||
JetType receiverType = resolveTypeRefWithDefault(functionLiteral.getReceiverTypeRef(), scope, temporaryTrace, null);
|
||||
return KotlinBuiltIns.getInstance().getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiverType, parameterTypes, returnType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetType resolveTypeRefWithDefault(
|
||||
@Nullable JetTypeReference returnTypeRef,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull BindingTrace trace,
|
||||
@Nullable JetType defaultValue
|
||||
) {
|
||||
if (returnTypeRef != null) {
|
||||
return expressionTypingServices.getTypeResolver().resolveType(scope, returnTypeRef, trace, true);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ import java.util.*;
|
||||
import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveMode;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveMode.RESOLVE_FUNCTION_ARGUMENTS;
|
||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
@@ -343,7 +345,7 @@ public class CallResolver {
|
||||
OverloadResolutionResultsImpl<D> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
|
||||
context.trace, tracing, candidates);
|
||||
if (!results.isSingleResult()) {
|
||||
argumentTypeResolver.checkTypesWithNoCallee(context);
|
||||
argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
@@ -405,6 +407,7 @@ public class CallResolver {
|
||||
debugInfo.set(ResolutionDebugInfo.RESULT, results.getResultingCall());
|
||||
}
|
||||
|
||||
resolveFunctionArguments(context, results);
|
||||
return results;
|
||||
}
|
||||
if (results.getResultCode() == OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE) {
|
||||
@@ -422,14 +425,31 @@ public class CallResolver {
|
||||
|
||||
debugInfo.set(ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResultingCall());
|
||||
}
|
||||
resolveFunctionArguments(context, resultsForFirstNonemptyCandidateSet);
|
||||
}
|
||||
else {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(reference));
|
||||
argumentTypeResolver.checkTypesWithNoCallee(context);
|
||||
argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
|
||||
}
|
||||
return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<F>nameNotFound();
|
||||
}
|
||||
|
||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> resolveFunctionArguments(
|
||||
@NotNull final BasicResolutionContext context,
|
||||
@NotNull OverloadResolutionResults<D> results
|
||||
) {
|
||||
if (results.isSingleResult()) {
|
||||
ResolvedCall<D> resolvedCall = results.getResultingCall();
|
||||
if (resolvedCall instanceof ResolvedCallImpl) {
|
||||
argumentTypeResolver.checkTypesForFunctionArguments(context, (ResolvedCallImpl<D>) resolvedCall);
|
||||
}
|
||||
}
|
||||
else {
|
||||
argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -26,12 +26,23 @@ import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CallResolverUtil {
|
||||
|
||||
public static final JetType PLACEHOLDER_FUNCTION_TYPE = ErrorUtils.createErrorType("Function type");
|
||||
public static final JetType PLACEHOLDER_FUNCTION_PARAMETER_TYPE = ErrorUtils.createErrorType("Function parameter type");
|
||||
|
||||
public enum ResolveMode {
|
||||
RESOLVE_FUNCTION_ARGUMENTS,
|
||||
SKIP_FUNCTION_ARGUMENTS
|
||||
}
|
||||
|
||||
private CallResolverUtil() {}
|
||||
|
||||
public static <D extends CallableDescriptor> ResolvedCallImpl<D> copy(@NotNull ResolvedCallImpl<D> call, @NotNull ResolutionContext context) {
|
||||
ResolutionCandidate<D> candidate = ResolutionCandidate.create(call.getCandidateDescriptor(), call.getThisObject(),
|
||||
call.getReceiverArgument(), call.getExplicitReceiverKind(),
|
||||
|
||||
@@ -39,8 +39,6 @@ import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
@@ -48,13 +46,16 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_IS_NOT_AN_EXPRESSION;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.PLACEHOLDER_FUNCTION_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveMode;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveMode.RESOLVE_FUNCTION_ARGUMENTS;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveMode.SKIP_FUNCTION_ARGUMENTS;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
public class CandidateResolver {
|
||||
@NotNull
|
||||
private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
|
||||
@NotNull
|
||||
private ArgumentTypeResolver argumentTypeResolver;
|
||||
@NotNull
|
||||
@@ -124,7 +125,7 @@ public class CandidateResolver {
|
||||
candidateCall.addStatus(status);
|
||||
}
|
||||
else {
|
||||
candidateCall.addStatus(checkAllValueArguments(context).status);
|
||||
candidateCall.addStatus(checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS).status);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -157,7 +158,7 @@ public class CandidateResolver {
|
||||
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
|
||||
candidateCall.recordTypeArgument(typeParameterDescriptor, typeArguments.get(i));
|
||||
}
|
||||
candidateCall.addStatus(checkAllValueArguments(context).status);
|
||||
candidateCall.addStatus(checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS).status);
|
||||
}
|
||||
else {
|
||||
candidateCall.addStatus(OTHER_ERROR);
|
||||
@@ -198,13 +199,14 @@ public class CandidateResolver {
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
|
||||
|
||||
for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
|
||||
if (!JetPsiUtil.isFunctionLiteralWithoutDeclaredParameterTypes(valueArgument.getArgumentExpression())) continue;
|
||||
if (!(valueArgument.getArgumentExpression() instanceof JetFunctionLiteralExpression)) continue;
|
||||
|
||||
ConstraintSystem systemWithCurrentSubstitution = constraintSystem.copy();
|
||||
addConstraintForValueArgument(valueArgument, valueParameterDescriptor, constraintSystem.getCurrentSubstitutor(),
|
||||
systemWithCurrentSubstitution, context, null);
|
||||
systemWithCurrentSubstitution, context, null, RESOLVE_FUNCTION_ARGUMENTS);
|
||||
if (systemWithCurrentSubstitution.hasContradiction() || systemWithCurrentSubstitution.hasErrorInConstrainingTypes()) {
|
||||
addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem, context, null);
|
||||
addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem, context,
|
||||
null, RESOLVE_FUNCTION_ARGUMENTS);
|
||||
}
|
||||
else {
|
||||
constraintSystem = systemWithCurrentSubstitution;
|
||||
@@ -219,7 +221,8 @@ public class CandidateResolver {
|
||||
|
||||
if (!constraintSystem.isSuccessful()) {
|
||||
resolvedCall.setResultingSubstitutor(constraintSystemWithoutExpectedTypeConstraint.getResultingSubstitutor());
|
||||
List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, resolvedCall.getTrace()).argumentTypes;
|
||||
List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, resolvedCall.getTrace(),
|
||||
RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
|
||||
JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
|
||||
context.tracing.typeInferenceFailed(resolvedCall.getTrace(),
|
||||
InferenceErrorData
|
||||
@@ -232,7 +235,7 @@ public class CandidateResolver {
|
||||
|
||||
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
|
||||
// Here we type check the arguments with inferred types expected
|
||||
checkAllValueArguments(context);
|
||||
checkAllValueArguments(context, RESOLVE_FUNCTION_ARGUMENTS);
|
||||
|
||||
checkBounds(resolvedCall, constraintSystem, resolvedCall.getTrace(), context.tracing);
|
||||
resolvedCall.setHasUnknownTypeParameters(false);
|
||||
@@ -280,7 +283,7 @@ public class CandidateResolver {
|
||||
// We'll type check the arguments later, with the inferred types expected
|
||||
boolean[] isErrorType = new boolean[1];
|
||||
addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintsSystem,
|
||||
context, isErrorType);
|
||||
context, isErrorType, SKIP_FUNCTION_ARGUMENTS);
|
||||
if (isErrorType[0]) {
|
||||
candidateCall.argumentHasNoType();
|
||||
}
|
||||
@@ -314,7 +317,7 @@ public class CandidateResolver {
|
||||
candidateCall.setHasUnknownTypeParameters(true);
|
||||
return SUCCESS;
|
||||
}
|
||||
ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context);
|
||||
ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS);
|
||||
ResolutionStatus argumentsStatus = checkingResult.status;
|
||||
List<JetType> argumentTypes = checkingResult.argumentTypes;
|
||||
JetType receiverType = candidateCall.getReceiverArgument().exists() ? candidateCall.getReceiverArgument().getType() : null;
|
||||
@@ -335,31 +338,28 @@ public class CandidateResolver {
|
||||
@NotNull TypeSubstitutor substitutor,
|
||||
@NotNull ConstraintSystem constraintSystem,
|
||||
@NotNull ResolutionContext context,
|
||||
@Nullable boolean[] isErrorType) {
|
||||
@Nullable boolean[] isErrorType,
|
||||
@NotNull ResolveMode resolveFunctionArgumentBodies) {
|
||||
|
||||
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
JetType type;
|
||||
if (argumentExpression != null) {
|
||||
TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(
|
||||
context.trace, "transient trace to resolve argument", argumentExpression);
|
||||
type = expressionTypingServices.getType(context.scope, argumentExpression,
|
||||
substitutor.substitute(effectiveExpectedType, Variance.INVARIANT), context.dataFlowInfo, traceForUnknown);
|
||||
}
|
||||
else {
|
||||
type = null;
|
||||
}
|
||||
TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(
|
||||
context.trace, "transient trace to resolve argument", argumentExpression);
|
||||
JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
|
||||
JetType type = argumentTypeResolver.getArgumentTypeInfo(argumentExpression, traceForUnknown, context.scope, context.dataFlowInfo,
|
||||
expectedType != null ? expectedType : NO_EXPECTED_TYPE, resolveFunctionArgumentBodies).getType();
|
||||
constraintSystem.addSubtypeConstraint(effectiveExpectedType, type, ConstraintPosition.getValueParameterPosition(
|
||||
valueParameterDescriptor.getIndex()));
|
||||
//todo no return
|
||||
if (isErrorType != null) {
|
||||
isErrorType[0] = type == null || ErrorUtils.isErrorType(type);
|
||||
}
|
||||
}
|
||||
|
||||
private <D extends CallableDescriptor, F extends D> ValueArgumentsCheckingResult checkAllValueArguments(CallResolutionContext<D, F> context) {
|
||||
private <D extends CallableDescriptor, F extends D> ValueArgumentsCheckingResult checkAllValueArguments(
|
||||
@NotNull CallResolutionContext<D, F> context,
|
||||
@NotNull ResolveMode resolveFunctionArgumentBodies) {
|
||||
ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(context, context.candidateCall,
|
||||
context.candidateCall.getTrace());
|
||||
context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
|
||||
ResolutionStatus resultStatus = checkingResult.status;
|
||||
ResolvedCall<D> candidateCall = context.candidateCall;
|
||||
|
||||
@@ -381,7 +381,8 @@ public class CandidateResolver {
|
||||
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkValueArgumentTypes(
|
||||
@NotNull ResolutionContext context,
|
||||
@NotNull ResolvedCallImpl<D> candidateCall,
|
||||
@NotNull BindingTrace trace) {
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull ResolveMode resolveFunctionArgumentBodies) {
|
||||
ResolutionStatus resultStatus = SUCCESS;
|
||||
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
||||
List<JetType> argumentTypes = Lists.newArrayList();
|
||||
@@ -398,17 +399,18 @@ public class CandidateResolver {
|
||||
if (TypeUtils.dependsOnTypeParameters(expectedType, candidateCall.getCandidateDescriptor().getTypeParameters())) {
|
||||
expectedType = NO_EXPECTED_TYPE;
|
||||
}
|
||||
JetTypeInfo typeInfo = expressionTypingServices.getTypeInfo(context.scope, expression, expectedType, dataFlowInfo, trace);
|
||||
JetTypeInfo typeInfo = argumentTypeResolver.getArgumentTypeInfo(expression, trace, context.scope, dataFlowInfo,
|
||||
expectedType, resolveFunctionArgumentBodies);
|
||||
JetType type = typeInfo.getType();
|
||||
dataFlowInfo = dataFlowInfo.and(typeInfo.getDataFlowInfo());
|
||||
|
||||
if (type == null || ErrorUtils.isErrorType(type)) {
|
||||
if (type == null || (ErrorUtils.isErrorType(type) && type != PLACEHOLDER_FUNCTION_TYPE)) {
|
||||
candidateCall.argumentHasNoType();
|
||||
argumentTypes.add(type);
|
||||
}
|
||||
else {
|
||||
JetType resultingType;
|
||||
if (expectedType == NO_EXPECTED_TYPE || typeChecker.isSubtypeOf(type, expectedType)) {
|
||||
if (expectedType == NO_EXPECTED_TYPE || argumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
|
||||
resultingType = type;
|
||||
}
|
||||
else {
|
||||
@@ -438,7 +440,7 @@ public class CandidateResolver {
|
||||
List<ReceiverValue> variants = AutoCastUtils.getAutoCastVariants(trace.getBindingContext(), dataFlowInfo, receiverToCast);
|
||||
for (ReceiverValue receiverValue : variants) {
|
||||
JetType possibleType = receiverValue.getType();
|
||||
if (typeChecker.isSubtypeOf(possibleType, expectedType)) {
|
||||
if (argumentTypeResolver.isSubtypeOfForArgumentType(possibleType, expectedType)) {
|
||||
return possibleType;
|
||||
}
|
||||
}
|
||||
@@ -467,7 +469,7 @@ public class CandidateResolver {
|
||||
: receiverArgumentType;
|
||||
if (!TypeUtils.dependsOnTypeParameters(receiverParameter.getType(),
|
||||
candidateCall.getCandidateDescriptor().getTypeParameters()) &&
|
||||
!typeChecker.isSubtypeOf(effectiveReceiverArgumentType, receiverParameter.getType())) {
|
||||
!argumentTypeResolver.isSubtypeOfForArgumentType(effectiveReceiverArgumentType, receiverParameter.getType())) {
|
||||
context.tracing.wrongReceiverType(context.candidateCall.getTrace(), receiverParameter, receiverArgument);
|
||||
result = OTHER_ERROR;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ fun test() {
|
||||
v1({}, {})
|
||||
v1({}, <!ERROR_COMPILE_TIME_VALUE!>1<!>, {})
|
||||
v1({}, {}, {it})
|
||||
v1({}) <!VARARG_OUTSIDE_PARENTHESES!>{}<!>
|
||||
v1({}) <!VARARG_OUTSIDE_PARENTHESES, DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED!>{}<!>
|
||||
v1 <!VARARG_OUTSIDE_PARENTHESES, DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED!>{}<!>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
object A {
|
||||
val iii = 42
|
||||
}
|
||||
|
||||
//inappropriate but participating in resolve functions
|
||||
//fun foo(s: String, a: Any) = s + a
|
||||
//fun foo(a: Any, s: String) = s + a
|
||||
//fun foo(i: Int, j: Int) = i + j
|
||||
//fun foo(a: Any, i: Int) = "$a$i"
|
||||
//fun foo(f: (Int)->Int, i: Int) = f(i)
|
||||
//fun foo(f: (String)->Int, s: String) = f(s)
|
||||
//fun foo(f: (Any)->Int, a: Any) = f(a)
|
||||
//fun foo(s: String, f: (String)->Int) = f(s)
|
||||
//fun foo(a: Any, f: (Any)->Int) = f(a)
|
||||
//appropriate function
|
||||
fun foo(i: Int, f: (Int)->Int) = f(i)
|
||||
|
||||
fun test() {
|
||||
foo(1) { (x1: Int):Int ->
|
||||
foo(2) { (x2: Int): Int ->
|
||||
foo(3) { (x3: Int): Int ->
|
||||
foo(4) { (x4: Int): Int ->
|
||||
foo(5) { (x5: Int): Int ->
|
||||
x1 + x2 + x3 + x4 + x5 + A.iii
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
object A {
|
||||
val iii = 42
|
||||
}
|
||||
|
||||
//inappropriate but participating in resolve functions
|
||||
fun foo(s: String, a: Any) = s + a
|
||||
fun foo(a: Any, s: String) = s + a
|
||||
fun foo(i: Int, j: Int) = i + j
|
||||
fun foo(a: Any, i: Int) = "$a$i"
|
||||
fun foo(f: (Int)->Int, i: Int) = f(i)
|
||||
fun foo(f: (String)->Int, s: String) = f(s)
|
||||
fun foo(f: (Any)->Int, a: Any) = f(a)
|
||||
fun foo(s: String, f: (String)->Int) = f(s)
|
||||
fun foo(a: Any, f: (Any)->Int) = f(a)
|
||||
//appropriate function
|
||||
fun foo(i: Int, f: (Int)->Int) = f(i)
|
||||
|
||||
fun test() {
|
||||
foo(1) { (x1: Int):Int ->
|
||||
foo(2) { (x2: Int): Int ->
|
||||
foo(3) { (x3: Int): Int ->
|
||||
foo(4) { (x4: Int): Int ->
|
||||
foo(5) { (x5: Int): Int ->
|
||||
x1 + x2 + x3 + x4 + x5 + A.iii
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3378,6 +3378,16 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/resolve"), "kt", true);
|
||||
}
|
||||
|
||||
@TestMetadata("resolveWithFunctionLiterals.kt")
|
||||
public void testResolveWithFunctionLiterals() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/resolve/resolveWithFunctionLiterals.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("resolveWithFunctionLiteralsOverload.kt")
|
||||
public void testResolveWithFunctionLiteralsOverload() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/resolve/resolveWithFunctionLiteralsOverload.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("resolveWithGenerics.kt")
|
||||
public void testResolveWithGenerics() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/resolve/resolveWithGenerics.kt");
|
||||
|
||||
Reference in New Issue
Block a user