complete inference for inner calls after resolve&inference of outer call finishes
deferredComputationsForArguments stored in ResolvedCallImpl, 'completeValueArgumentsInference' completes inference for inner calls recursively
This commit is contained in:
+13
-7
@@ -157,8 +157,10 @@ public class CallExpressionResolver {
|
|||||||
if (!results.isNothing()) {
|
if (!results.isNothing()) {
|
||||||
checkSuper(receiver, results, context.trace, callExpression);
|
checkSuper(receiver, results, context.trace, callExpression);
|
||||||
result[0] = true;
|
result[0] = true;
|
||||||
if (results.isIncomplete()) {
|
if (results.isSingleResult() && resolveMode == ResolveMode.NORMAL) {
|
||||||
return null;
|
if (CallResolverUtil.hasReturnTypeDependentOnNotInferredParams(results.getResultingCall())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return results.isSingleResult() ? results.getResultingCall() : null;
|
return results.isSingleResult() ? results.getResultingCall() : null;
|
||||||
}
|
}
|
||||||
@@ -246,12 +248,14 @@ public class CallExpressionResolver {
|
|||||||
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode
|
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode
|
||||||
) {
|
) {
|
||||||
TypeInfoForCall typeInfoForCall = getCallExpressionExtendedTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context, resolveMode);
|
TypeInfoForCall typeInfoForCall = getCallExpressionExtendedTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context, resolveMode);
|
||||||
DataFlowUtils.checkType(typeInfoForCall.getType(), callExpression, context, typeInfoForCall.getDataFlowInfo());
|
if (resolveMode == ResolveMode.NORMAL) {
|
||||||
|
DataFlowUtils.checkType(typeInfoForCall.getType(), callExpression, context, typeInfoForCall.getDataFlowInfo());
|
||||||
|
}
|
||||||
return typeInfoForCall;
|
return typeInfoForCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private TypeInfoForCall getCallExpressionExtendedTypeInfoWithoutFinalTypeCheck(
|
public TypeInfoForCall getCallExpressionExtendedTypeInfoWithoutFinalTypeCheck(
|
||||||
@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
|
@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
|
||||||
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode
|
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode
|
||||||
) {
|
) {
|
||||||
@@ -385,8 +389,10 @@ public class CallExpressionResolver {
|
|||||||
if (selectorReturnType != null) {
|
if (selectorReturnType != null) {
|
||||||
context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType);
|
context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType);
|
||||||
}
|
}
|
||||||
return TypeInfoForCall.create(
|
JetTypeInfo typeInfo = JetTypeInfo.create(selectorReturnType, selectorReturnTypeInfo.getDataFlowInfo());
|
||||||
DataFlowUtils.checkType(selectorReturnType, expression, context, selectorReturnTypeInfo.getDataFlowInfo()),
|
if (resolveMode == ResolveMode.NORMAL) {
|
||||||
selectorReturnTypeInfo);
|
DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo());
|
||||||
|
}
|
||||||
|
return TypeInfoForCall.create(typeInfo, selectorReturnTypeInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,85 +278,76 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
if (results == null) {
|
if (results == null) {
|
||||||
BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
|
BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
|
||||||
OverloadResolutionResults<F> resultsWithFixedResolve = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
|
results = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
|
||||||
if (resultsWithFixedResolve instanceof OverloadResolutionResultsImpl) {
|
if (results instanceof OverloadResolutionResultsImpl) {
|
||||||
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) resultsWithFixedResolve).getTrace();
|
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
|
||||||
if (deltasTraceForTypeInference != null) {
|
if (deltasTraceForTypeInference != null) {
|
||||||
deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
|
deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
results = completeTypeInferenceDependentOnFunctionLiterals(newContext, resultsWithFixedResolve, TracingStrategy.EMPTY);
|
completeTypeInferenceDependentOnFunctionLiterals(newContext, results, TracingStrategy.EMPTY);
|
||||||
cacheResults(resolutionResultsSlice, context, results, traceToResolveCall);
|
cacheResults(resolutionResultsSlice, context, results, traceToResolveCall);
|
||||||
}
|
}
|
||||||
|
traceToResolveCall.commit();
|
||||||
|
|
||||||
if (prioritizedTasks.isEmpty()) {
|
if (prioritizedTasks.isEmpty()) {
|
||||||
traceToResolveCall.commit();
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
if (context.resolveMode == ResolveMode.INTERNAL) return results;
|
||||||
|
|
||||||
TracingStrategy tracing = prioritizedTasks.iterator().next().tracing;
|
TracingStrategy tracing = prioritizedTasks.iterator().next().tracing;
|
||||||
OverloadResolutionResults<F> completeResults = completeTypeInferenceDependentOnExpectedType(
|
return completeTypeInferenceDependentOnExpectedType(context, results, tracing);
|
||||||
context.replaceBindingTrace(traceToResolveCall), results, tracing);
|
|
||||||
traceToResolveCall.commit();
|
|
||||||
return completeResults;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> completeTypeInferenceDependentOnFunctionLiterals(
|
private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
|
||||||
@NotNull BasicCallResolutionContext context,
|
@NotNull BasicCallResolutionContext context,
|
||||||
@NotNull OverloadResolutionResults<D> resultsWithIncompleteTypeInference,
|
@NotNull OverloadResolutionResults<D> results,
|
||||||
@NotNull TracingStrategy tracing
|
@NotNull TracingStrategy tracing
|
||||||
) {
|
) {
|
||||||
if (resultsWithIncompleteTypeInference.getResultCode() != OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE) {
|
if (results.getResultCode() != OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE) return;
|
||||||
return resultsWithIncompleteTypeInference;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<ResolvedCallWithTrace<D>> candidates = Sets.newLinkedHashSet(
|
//todo[ResolvedCallImpl] get rid of instanceof & cast
|
||||||
(Collection<? extends ResolvedCallWithTrace<D>>) resultsWithIncompleteTypeInference.getResultingCalls());
|
if (!results.isSingleResult() || !(results.getResultingCall() instanceof ResolvedCallImpl)) {
|
||||||
ResolvedCallWithTrace<D> maximallySpecific = OverloadingConflictResolver.INSTANCE.findMaximallySpecific(candidates, false);
|
argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
|
||||||
if (maximallySpecific != null && maximallySpecific instanceof ResolvedCallImpl) {
|
return;
|
||||||
candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(
|
|
||||||
CallCandidateResolutionContext.createForCallBeingAnalyzed((ResolvedCallImpl<D>) maximallySpecific, context, tracing));
|
|
||||||
for (ResolvedCallWithTrace<D> callWithUnknownTypeParameters : candidates) {
|
|
||||||
if (callWithUnknownTypeParameters != maximallySpecific) {
|
|
||||||
((ResolvedCallImpl<D>) callWithUnknownTypeParameters).addStatus(ResolutionStatus.OTHER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OverloadResolutionResultsImpl.incompleteTypeInference(Collections.singleton(maximallySpecific));
|
|
||||||
}
|
}
|
||||||
for (ResolvedCallWithTrace<D> callWithUnknownTypeParameters : candidates) {
|
CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
|
||||||
ResolvedCallImpl<D> resolvedCall = (ResolvedCallImpl<D>) callWithUnknownTypeParameters;
|
(ResolvedCallImpl<D>) results.getResultingCall(), context, tracing);
|
||||||
resolvedCall.addStatus(ResolutionStatus.INCOMPLETE_TYPE_INFERENCE);
|
candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
|
||||||
}
|
|
||||||
return OverloadResolutionResultsImpl.incompleteTypeInference(candidates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> completeTypeInferenceDependentOnExpectedType(
|
private <D extends CallableDescriptor> OverloadResolutionResults<D> completeTypeInferenceDependentOnExpectedType(
|
||||||
@NotNull BasicCallResolutionContext context,
|
@NotNull BasicCallResolutionContext context,
|
||||||
@NotNull OverloadResolutionResults<D> resultsWithIncompleteTypeInference,
|
@NotNull OverloadResolutionResults<D> results,
|
||||||
@NotNull TracingStrategy tracing
|
@NotNull TracingStrategy tracing
|
||||||
) {
|
) {
|
||||||
if (resultsWithIncompleteTypeInference.getResultCode() != OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE) {
|
if (results.isSingleResult()) {
|
||||||
return resultsWithIncompleteTypeInference;
|
ResolvedCall<D> call = results.getResultingCall();
|
||||||
}
|
if (call instanceof ResolvedCallImpl) {
|
||||||
|
argumentTypeResolver.checkUnmappedArgumentTypes(context, ((ResolvedCallImpl<D>)call).getUnmappedArguments());
|
||||||
Set<ResolvedCallWithTrace<D>> resultingCalls = null;
|
|
||||||
if (resultsWithIncompleteTypeInference.isSingleResult()) {
|
|
||||||
ResolvedCallWithTrace<D> resolvedCall = (ResolvedCallWithTrace<D>) resultsWithIncompleteTypeInference.getResultingCall();
|
|
||||||
if (resolvedCall.hasUnknownTypeParameters() && resolvedCall instanceof ResolvedCallImpl) {
|
|
||||||
ResolvedCallImpl<D> copy = CallResolverUtil.copy((ResolvedCallImpl<D>) resolvedCall, context);
|
|
||||||
candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(
|
|
||||||
CallCandidateResolutionContext.createForCallBeingAnalyzed(copy, context, tracing));
|
|
||||||
resultingCalls = Collections.<ResolvedCallWithTrace<D>>singleton(copy);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resultingCalls == null) {
|
|
||||||
resultingCalls = (Set<ResolvedCallWithTrace<D>>) resultsWithIncompleteTypeInference.getResultingCalls();
|
if (!results.isSingleResult()) return results;
|
||||||
|
|
||||||
|
ResolvedCallWithTrace<D> resolvedCall = (ResolvedCallWithTrace<D>) results.getResultingCall();
|
||||||
|
//todo[ResolvedCallImpl]
|
||||||
|
if (!(resolvedCall instanceof ResolvedCallImpl)) return results;
|
||||||
|
if (!resolvedCall.hasUnknownTypeParameters()) {
|
||||||
|
CallCandidateResolutionContext<D> callCandidateResolutionContext =
|
||||||
|
CallCandidateResolutionContext.createForCallBeingAnalyzed((ResolvedCallImpl<D>) resolvedCall, context, tracing);
|
||||||
|
candidateResolver.completeValueArgumentsInference(callCandidateResolutionContext);
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
OverloadResolutionResultsImpl<D> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
|
ResolvedCallImpl<D> copy = CallResolverUtil.copy((ResolvedCallImpl<D>) resolvedCall, context);
|
||||||
context.trace, tracing, resultingCalls);
|
CallCandidateResolutionContext<D> callCandidateResolutionContext =
|
||||||
if (!results.isSingleResult()) {
|
CallCandidateResolutionContext.createForCallBeingAnalyzed(copy, context, tracing);
|
||||||
argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
|
candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext);
|
||||||
|
|
||||||
|
if (copy.getStatus().isSuccess()) {
|
||||||
|
return OverloadResolutionResultsImpl.success(copy);
|
||||||
}
|
}
|
||||||
return results;
|
return OverloadResolutionResultsImpl.incompleteTypeInference(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <F extends CallableDescriptor> void cacheResults(@NotNull WritableSlice<CallKey, OverloadResolutionResults<F>> resolutionResultsSlice,
|
private <F extends CallableDescriptor> void cacheResults(@NotNull WritableSlice<CallKey, OverloadResolutionResults<F>> resolutionResultsSlice,
|
||||||
@@ -407,9 +398,8 @@ public class CallResolver {
|
|||||||
OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
|
OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
|
||||||
for (ResolutionTask<D, F> task : prioritizedTasks) {
|
for (ResolutionTask<D, F> task : prioritizedTasks) {
|
||||||
TemporaryBindingTrace taskTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.reference);
|
TemporaryBindingTrace taskTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.reference);
|
||||||
OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(task.replaceBindingTrace(
|
OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(
|
||||||
taskTrace),
|
task.replaceBindingTrace(taskTrace), callTransformer, context.trace);
|
||||||
callTransformer, context.trace);
|
|
||||||
if (results.isSuccess() || results.isAmbiguity()) {
|
if (results.isSuccess() || results.isAmbiguity()) {
|
||||||
taskTrace.commit();
|
taskTrace.commit();
|
||||||
|
|
||||||
|
|||||||
@@ -21,18 +21,24 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.ValueArgument;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
|
import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
|
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
|
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class CallResolverUtil {
|
public class CallResolverUtil {
|
||||||
|
|
||||||
@@ -74,6 +80,11 @@ public class CallResolverUtil {
|
|||||||
copy.recordValueArgument(entry.getKey(), entry.getValue());
|
copy.recordValueArgument(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
copy.setInitialDataFlowInfo(call.getDataFlowInfo());
|
copy.setInitialDataFlowInfo(call.getDataFlowInfo());
|
||||||
|
for (ResolvedValueArgument resolvedArgument : call.getValueArguments().values()) {
|
||||||
|
for (ValueArgument argument : resolvedArgument.getArguments()) {
|
||||||
|
copy.addDeferredComputationForArgument(argument, call.getDeferredComputationForArgument(argument));
|
||||||
|
}
|
||||||
|
}
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,4 +124,26 @@ public class CallResolverUtil {
|
|||||||
newArguments.add(new TypeProjection(Variance.INVARIANT, DONT_CARE));
|
newArguments.add(new TypeProjection(Variance.INVARIANT, DONT_CARE));
|
||||||
return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
|
return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <D extends CallableDescriptor> boolean hasReturnTypeDependentOnNotInferredParams(@NotNull ResolvedCall<D> resolvedCall) {
|
||||||
|
//todo[ResolvedCallImpl]
|
||||||
|
if (!(resolvedCall instanceof ResolvedCallImpl)) return false;
|
||||||
|
ResolvedCallImpl call = (ResolvedCallImpl) resolvedCall;
|
||||||
|
ConstraintSystem constraintSystem = call.getConstraintSystem();
|
||||||
|
if (constraintSystem == null) return false;
|
||||||
|
|
||||||
|
CallableDescriptor candidateDescriptor = call.getCandidateDescriptor();
|
||||||
|
JetType returnType = candidateDescriptor.getReturnType();
|
||||||
|
if (returnType == null) return false;
|
||||||
|
|
||||||
|
for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
|
||||||
|
JetType inferredValueForTypeVariable = ConstraintsUtil.getValue(constraintSystem.getTypeConstraints(typeVariable));
|
||||||
|
if (inferredValueForTypeVariable == null) {
|
||||||
|
if (TypeUtils.dependsOnTypeParameters(returnType, Collections.singleton(typeVariable))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.*;
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.*;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
|
import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
|
import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.TypeInfoForCall;
|
import org.jetbrains.jet.lang.resolve.calls.context.TypeInfoForCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.inference.*;
|
import org.jetbrains.jet.lang.resolve.calls.inference.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
@@ -55,6 +56,7 @@ import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgum
|
|||||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SKIP_FUNCTION_ARGUMENTS;
|
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SKIP_FUNCTION_ARGUMENTS;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*;
|
import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*;
|
||||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||||
|
import static org.jetbrains.jet.lang.types.TypeUtils.canHaveSubtypes;
|
||||||
|
|
||||||
public class CandidateResolver {
|
public class CandidateResolver {
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -107,7 +109,7 @@ public class CandidateResolver {
|
|||||||
argumentTypeResolver.checkTypesWithNoCallee(context.toBasic());
|
argumentTypeResolver.checkTypesWithNoCallee(context.toBasic());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
argumentTypeResolver.checkUnmappedArgumentTypes(context.toBasic(), unmappedArguments);
|
candidateCall.setUnmappedArguments(unmappedArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
|
List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
|
||||||
@@ -138,7 +140,8 @@ public class CandidateResolver {
|
|||||||
|
|
||||||
Map<TypeConstructor, TypeProjection>
|
Map<TypeConstructor, TypeProjection>
|
||||||
substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor)candidate, typeArguments);
|
substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor)candidate, typeArguments);
|
||||||
candidateCall.setResultingSubstitutor(TypeSubstitutor.create(substitutionContext));
|
TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
|
||||||
|
candidateCall.setResultingSubstitutor(substitutor);
|
||||||
|
|
||||||
List<TypeParameterDescriptor> typeParameters = candidateCall.getCandidateDescriptor().getTypeParameters();
|
List<TypeParameterDescriptor> typeParameters = candidateCall.getCandidateDescriptor().getTypeParameters();
|
||||||
for (int i = 0; i < typeParameters.size(); i++) {
|
for (int i = 0; i < typeParameters.size(); i++) {
|
||||||
@@ -206,6 +209,7 @@ public class CandidateResolver {
|
|||||||
addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
|
addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public <D extends CallableDescriptor> void completeTypeInferenceDependentOnExpectedTypeForCall(
|
public <D extends CallableDescriptor> void completeTypeInferenceDependentOnExpectedTypeForCall(
|
||||||
@@ -224,10 +228,11 @@ public class CandidateResolver {
|
|||||||
|
|
||||||
if (!constraintSystem.isSuccessful()) {
|
if (!constraintSystem.isSuccessful()) {
|
||||||
resolvedCall.setResultingSubstitutor(constraintSystemWithoutExpectedTypeConstraint.getResultingSubstitutor());
|
resolvedCall.setResultingSubstitutor(constraintSystemWithoutExpectedTypeConstraint.getResultingSubstitutor());
|
||||||
List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, resolvedCall.getTrace(),
|
completeValueArgumentsInference(context);
|
||||||
|
List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, context.trace,
|
||||||
RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
|
RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
|
||||||
JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
|
JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
|
||||||
context.tracing.typeInferenceFailed(resolvedCall.getTrace(),
|
context.tracing.typeInferenceFailed(context.trace,
|
||||||
InferenceErrorData
|
InferenceErrorData
|
||||||
.create(descriptor, constraintSystem, argumentTypes, receiverType,
|
.create(descriptor, constraintSystem, argumentTypes, receiverType,
|
||||||
context.expectedType),
|
context.expectedType),
|
||||||
@@ -246,16 +251,52 @@ public class CandidateResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!boundsAreSatisfied) {
|
if (!boundsAreSatisfied) {
|
||||||
context.tracing.upperBoundViolated(resolvedCall.getTrace(), InferenceErrorData.create(resolvedCall.getCandidateDescriptor(), constraintSystem));
|
context.tracing.upperBoundViolated(context.trace, InferenceErrorData.create(resolvedCall.getCandidateDescriptor(), constraintSystem));
|
||||||
}
|
}
|
||||||
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
|
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
|
||||||
|
|
||||||
|
completeValueArgumentsInference(context);
|
||||||
// Here we type check the arguments with inferred types expected
|
// Here we type check the arguments with inferred types expected
|
||||||
checkAllValueArguments(context, RESOLVE_FUNCTION_ARGUMENTS);
|
checkAllValueArguments(context, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
|
||||||
|
|
||||||
resolvedCall.setHasUnknownTypeParameters(false);
|
resolvedCall.setHasUnknownTypeParameters(false);
|
||||||
if (resolvedCall.getStatus() == ResolutionStatus.UNKNOWN_STATUS) {
|
ResolutionStatus status = resolvedCall.getStatus();
|
||||||
resolvedCall.addStatus(ResolutionStatus.SUCCESS);
|
if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
|
||||||
|
resolvedCall.setStatusToSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <D extends CallableDescriptor> void completeValueArgumentsInference(
|
||||||
|
@NotNull CallCandidateResolutionContext<D> context
|
||||||
|
) {
|
||||||
|
ResolvedCallImpl<D> resolvedCall = context.candidateCall;
|
||||||
|
ConstraintSystem constraintSystem = context.candidateCall.getConstraintSystem();
|
||||||
|
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
|
||||||
|
ValueParameterDescriptor parameterDescriptor = entry.getKey();
|
||||||
|
ResolvedValueArgument resolvedArgument = entry.getValue();
|
||||||
|
|
||||||
|
for (ValueArgument argument : resolvedArgument.getArguments()) {
|
||||||
|
JetExpression expression = argument.getArgumentExpression();
|
||||||
|
if (expression == null) continue;
|
||||||
|
|
||||||
|
JetType effectiveExpectedType = getEffectiveExpectedType(parameterDescriptor, argument);
|
||||||
|
JetType expectedType = constraintSystem != null
|
||||||
|
? constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
|
||||||
|
: effectiveExpectedType;
|
||||||
|
|
||||||
|
CallCandidateResolutionContext<FunctionDescriptor> storedContextForArgument =
|
||||||
|
resolvedCall.getDeferredComputationForArgument(argument);
|
||||||
|
if (storedContextForArgument == null) continue;
|
||||||
|
|
||||||
|
CallCandidateResolutionContext<FunctionDescriptor> contextForArgument =
|
||||||
|
storedContextForArgument.replaceResolveMode(ResolveMode.NORMAL).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
|
||||||
|
if (contextForArgument.candidateCall.hasUnknownTypeParameters()) {
|
||||||
|
completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
completeValueArgumentsInference(contextForArgument);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,31 +414,21 @@ public class CandidateResolver {
|
|||||||
// Solution
|
// Solution
|
||||||
boolean hasContradiction = constraintSystem.hasContradiction();
|
boolean hasContradiction = constraintSystem.hasContradiction();
|
||||||
boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/false);
|
boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/false);
|
||||||
|
candidateCall.setHasUnknownTypeParameters(true);
|
||||||
if (!hasContradiction && boundsAreSatisfied) {
|
if (!hasContradiction && boundsAreSatisfied) {
|
||||||
candidateCall.setHasUnknownTypeParameters(true);
|
return INCOMPLETE_TYPE_INFERENCE;
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS);
|
ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS);
|
||||||
ResolutionStatus argumentsStatus = checkingResult.status;
|
ResolutionStatus argumentsStatus = checkingResult.status;
|
||||||
List<JetType> argumentTypes = checkingResult.argumentTypes;
|
|
||||||
JetType receiverType = candidateCall.getReceiverArgument().exists() ? candidateCall.getReceiverArgument().getType() : null;
|
|
||||||
InferenceErrorData.ExtendedInferenceErrorData inferenceErrorData = InferenceErrorData
|
|
||||||
.create(candidate, constraintSystemWithRightTypeParameters, argumentTypes, receiverType, context.expectedType);
|
|
||||||
if (hasContradiction) {
|
|
||||||
context.tracing.typeInferenceFailed(candidateCall.getTrace(), inferenceErrorData, constraintSystemWithRightTypeParameters);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
context.tracing.upperBoundViolated(candidateCall.getTrace(), inferenceErrorData);
|
|
||||||
}
|
|
||||||
return OTHER_ERROR.combine(argumentsStatus);
|
return OTHER_ERROR.combine(argumentsStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <C extends CallResolutionContext<C>> void addConstraintForValueArgument(
|
private <D extends CallableDescriptor> void addConstraintForValueArgument(
|
||||||
@NotNull ValueArgument valueArgument,
|
@NotNull ValueArgument valueArgument,
|
||||||
@NotNull ValueParameterDescriptor valueParameterDescriptor,
|
@NotNull ValueParameterDescriptor valueParameterDescriptor,
|
||||||
@NotNull TypeSubstitutor substitutor,
|
@NotNull TypeSubstitutor substitutor,
|
||||||
@NotNull ConstraintSystem constraintSystem,
|
@NotNull ConstraintSystem constraintSystem,
|
||||||
@NotNull CallResolutionContext<C> context,
|
@NotNull CallCandidateResolutionContext<D> context,
|
||||||
@Nullable boolean[] isErrorType,
|
@Nullable boolean[] isErrorType,
|
||||||
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
|
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
|
||||||
|
|
||||||
@@ -406,13 +437,17 @@ public class CandidateResolver {
|
|||||||
TemporaryBindingTrace traceToResolveArgument = TemporaryBindingTrace.create(
|
TemporaryBindingTrace traceToResolveArgument = TemporaryBindingTrace.create(
|
||||||
context.trace, "transient trace to resolve argument", argumentExpression);
|
context.trace, "transient trace to resolve argument", argumentExpression);
|
||||||
JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
|
JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
|
||||||
CallResolutionContext newContext =
|
CallResolutionContext newContext = context.replaceBindingTrace(traceToResolveArgument).replaceExpectedType(expectedType);
|
||||||
context.replaceBindingTrace(traceToResolveArgument).replaceExpectedType(
|
TypeInfoForCall typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(argumentExpression, newContext,
|
||||||
expectedType != null ? expectedType : NO_EXPECTED_TYPE);
|
resolveFunctionArgumentBodies);
|
||||||
JetType type = argumentTypeResolver.getArgumentTypeInfo(argumentExpression, newContext, resolveFunctionArgumentBodies).getType();
|
CallCandidateResolutionContext<FunctionDescriptor> contextForArgument = typeInfoForCall.getCallCandidateResolutionContext();
|
||||||
|
if (contextForArgument != null) {
|
||||||
|
context.candidateCall.addDeferredComputationForArgument(valueArgument, contextForArgument);
|
||||||
|
traceToResolveArgument.commit();
|
||||||
|
}
|
||||||
|
JetType type = typeInfoForCall.getType();
|
||||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
|
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
|
||||||
valueParameterDescriptor.getIndex()));
|
valueParameterDescriptor.getIndex()));
|
||||||
BindingContextUtils.commitResolutionCacheData(traceToResolveArgument, context.trace);
|
|
||||||
if (isErrorType != null) {
|
if (isErrorType != null) {
|
||||||
isErrorType[0] = type == null || ErrorUtils.isErrorType(type);
|
isErrorType[0] = type == null || ErrorUtils.isErrorType(type);
|
||||||
}
|
}
|
||||||
@@ -421,8 +456,16 @@ public class CandidateResolver {
|
|||||||
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
|
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
|
||||||
@NotNull CallCandidateResolutionContext<D> context,
|
@NotNull CallCandidateResolutionContext<D> context,
|
||||||
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
|
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
|
||||||
ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(context, context.candidateCall,
|
return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
|
||||||
context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
|
}
|
||||||
|
|
||||||
|
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
|
||||||
|
@NotNull CallCandidateResolutionContext<D> context,
|
||||||
|
@NotNull BindingTrace trace,
|
||||||
|
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
|
||||||
|
) {
|
||||||
|
ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(
|
||||||
|
context, context.candidateCall, trace, resolveFunctionArgumentBodies);
|
||||||
ResolutionStatus resultStatus = checkingResult.status;
|
ResolutionStatus resultStatus = checkingResult.status;
|
||||||
ResolvedCall<D> candidateCall = context.candidateCall;
|
ResolvedCall<D> candidateCall = context.candidateCall;
|
||||||
|
|
||||||
@@ -431,13 +474,17 @@ public class CandidateResolver {
|
|||||||
// both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
|
// both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
|
||||||
// Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
|
// Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
|
||||||
|
|
||||||
resultStatus = resultStatus.combine(checkReceiver(context, candidateCall, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument(),
|
resultStatus = resultStatus.combine(checkReceiver(
|
||||||
candidateCall.getExplicitReceiverKind().isReceiver(), false));
|
context, candidateCall, trace,
|
||||||
|
candidateCall.getResultingDescriptor().getReceiverParameter(),
|
||||||
|
candidateCall.getReceiverArgument(), candidateCall.getExplicitReceiverKind().isReceiver(), false));
|
||||||
|
|
||||||
resultStatus = resultStatus.combine(checkReceiver(context, candidateCall, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
|
resultStatus = resultStatus.combine(checkReceiver(
|
||||||
candidateCall.getExplicitReceiverKind().isThisObject(),
|
context, candidateCall, trace,
|
||||||
// for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
|
candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
|
||||||
context.call instanceof CallTransformer.CallForImplicitInvoke));
|
candidateCall.getExplicitReceiverKind().isThisObject(),
|
||||||
|
// for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
|
||||||
|
context.call instanceof CallTransformer.CallForImplicitInvoke));
|
||||||
return new ValueArgumentsCheckingResult(resultStatus, checkingResult.argumentTypes);
|
return new ValueArgumentsCheckingResult(resultStatus, checkingResult.argumentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,6 +514,7 @@ public class CandidateResolver {
|
|||||||
expression, newContext, resolveFunctionArgumentBodies);
|
expression, newContext, resolveFunctionArgumentBodies);
|
||||||
JetType type = typeInfoForCall.getType();
|
JetType type = typeInfoForCall.getType();
|
||||||
candidateCall.addDataFlowInfo(typeInfoForCall.getDataFlowInfo());
|
candidateCall.addDataFlowInfo(typeInfoForCall.getDataFlowInfo());
|
||||||
|
candidateCall.addDeferredComputationForArgument(argument, typeInfoForCall.getCallCandidateResolutionContext());
|
||||||
|
|
||||||
if (type == null || (ErrorUtils.isErrorType(type) && type != PLACEHOLDER_FUNCTION_TYPE)) {
|
if (type == null || (ErrorUtils.isErrorType(type) && type != PLACEHOLDER_FUNCTION_TYPE)) {
|
||||||
candidateCall.argumentHasNoType();
|
candidateCall.argumentHasNoType();
|
||||||
@@ -511,11 +559,12 @@ public class CandidateResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> ResolutionStatus checkReceiver(CallCandidateResolutionContext<D> context, ResolvedCall<D> candidateCall,
|
private <D extends CallableDescriptor> ResolutionStatus checkReceiver(
|
||||||
|
CallCandidateResolutionContext<D> context, ResolvedCall<D> candidateCall, BindingTrace trace,
|
||||||
ReceiverParameterDescriptor receiverParameter, ReceiverValue receiverArgument,
|
ReceiverParameterDescriptor receiverParameter, ReceiverValue receiverArgument,
|
||||||
boolean isExplicitReceiver, boolean implicitInvokeCheck) {
|
boolean isExplicitReceiver, boolean implicitInvokeCheck) {
|
||||||
|
|
||||||
BindingContext bindingContext = context.candidateCall.getTrace().getBindingContext();
|
BindingContext bindingContext = trace.getBindingContext();
|
||||||
|
|
||||||
ResolutionStatus result = SUCCESS;
|
ResolutionStatus result = SUCCESS;
|
||||||
if (receiverParameter != null && receiverArgument.exists()) {
|
if (receiverParameter != null && receiverArgument.exists()) {
|
||||||
@@ -524,7 +573,7 @@ public class CandidateResolver {
|
|||||||
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, bindingContext);
|
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, bindingContext);
|
||||||
if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
|
if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
|
||||||
|
|
||||||
context.tracing.unsafeCall(context.candidateCall.getTrace(), receiverArgumentType, implicitInvokeCheck);
|
context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
|
||||||
result = UNSAFE_CALL_ERROR;
|
result = UNSAFE_CALL_ERROR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -534,13 +583,13 @@ public class CandidateResolver {
|
|||||||
if (!TypeUtils.dependsOnTypeParameters(receiverParameter.getType(),
|
if (!TypeUtils.dependsOnTypeParameters(receiverParameter.getType(),
|
||||||
candidateCall.getCandidateDescriptor().getTypeParameters()) &&
|
candidateCall.getCandidateDescriptor().getTypeParameters()) &&
|
||||||
!argumentTypeResolver.isSubtypeOfForArgumentType(effectiveReceiverArgumentType, receiverParameter.getType())) {
|
!argumentTypeResolver.isSubtypeOfForArgumentType(effectiveReceiverArgumentType, receiverParameter.getType())) {
|
||||||
context.tracing.wrongReceiverType(context.candidateCall.getTrace(), receiverParameter, receiverArgument);
|
context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
|
||||||
result = OTHER_ERROR;
|
result = OTHER_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataFlowValue receiverValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(receiverArgument, bindingContext);
|
DataFlowValue receiverValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(receiverArgument, bindingContext);
|
||||||
if (safeAccess && !context.dataFlowInfo.getNullability(receiverValue).canBeNull()) {
|
if (safeAccess && !context.dataFlowInfo.getNullability(receiverValue).canBeNull()) {
|
||||||
context.tracing.unnecessarySafeCall(context.candidateCall.getTrace(), receiverArgumentType);
|
context.tracing.unnecessarySafeCall(trace, receiverArgumentType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+2
-1
@@ -58,8 +58,9 @@ public class TypeInfoForCall {
|
|||||||
if (resolvedCall instanceof ResolvedCallImpl) {
|
if (resolvedCall instanceof ResolvedCallImpl) {
|
||||||
BasicCallResolutionContext basicCallResolutionContext = BasicCallResolutionContext.create(
|
BasicCallResolutionContext basicCallResolutionContext = BasicCallResolutionContext.create(
|
||||||
TRACE_STUB, context.scope, call, TypeUtils.NO_EXPECTED_TYPE, typeInfo.getDataFlowInfo(), resolveMode, context.namespacesAllowed);
|
TRACE_STUB, context.scope, call, TypeUtils.NO_EXPECTED_TYPE, typeInfo.getDataFlowInfo(), resolveMode, context.namespacesAllowed);
|
||||||
|
//todo[ResolvedCallImpl]
|
||||||
callCandidateResolutionContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
|
callCandidateResolutionContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
|
||||||
(ResolvedCallImpl<FunctionDescriptor>) resolvedCall, basicCallResolutionContext, TracingStrategy.EMPTY);
|
(ResolvedCallImpl<FunctionDescriptor>) resolvedCall, basicCallResolutionContext, ((ResolvedCallImpl<FunctionDescriptor>) resolvedCall).getTracing());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
callCandidateResolutionContext = null;
|
callCandidateResolutionContext = null;
|
||||||
|
|||||||
+37
-3
@@ -17,14 +17,18 @@
|
|||||||
package org.jetbrains.jet.lang.resolve.calls.model;
|
package org.jetbrains.jet.lang.resolve.calls.model;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.ValueArgument;
|
||||||
import org.jetbrains.jet.lang.resolve.*;
|
import org.jetbrains.jet.lang.resolve.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
|
import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
|
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
|
import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
|
||||||
@@ -34,10 +38,9 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
|||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS;
|
import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS;
|
||||||
|
|
||||||
public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedCallWithTrace<D> {
|
public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedCallWithTrace<D> {
|
||||||
@@ -71,6 +74,8 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
|
|
||||||
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
|
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
|
||||||
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newLinkedHashMap();
|
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newLinkedHashMap();
|
||||||
|
private final Map<ValueArgument, CallCandidateResolutionContext<FunctionDescriptor>> deferredComputationsForArguments = Maps.newLinkedHashMap();
|
||||||
|
private final Set<ValueArgument> unmappedArguments = Sets.newLinkedHashSet();
|
||||||
private boolean someArgumentHasNoType = false;
|
private boolean someArgumentHasNoType = false;
|
||||||
private final DelegatingBindingTrace trace;
|
private final DelegatingBindingTrace trace;
|
||||||
private final TracingStrategy tracing;
|
private final TracingStrategy tracing;
|
||||||
@@ -99,6 +104,11 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
this.status = this.status.combine(status);
|
this.status = this.status.combine(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setStatusToSuccess() {
|
||||||
|
assert status == INCOMPLETE_TYPE_INFERENCE || status == UNKNOWN_STATUS;
|
||||||
|
status = ResolutionStatus.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasUnknownTypeParameters() {
|
public boolean hasUnknownTypeParameters() {
|
||||||
return hasUnknownTypeParameters;
|
return hasUnknownTypeParameters;
|
||||||
@@ -168,6 +178,16 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
valueArguments.put(valueParameter, valueArgument);
|
valueArguments.put(valueParameter, valueArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setUnmappedArguments(@NotNull Collection<ValueArgument> unmappedArguments) {
|
||||||
|
this.unmappedArguments.addAll(unmappedArguments);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Set<ValueArgument> getUnmappedArguments() {
|
||||||
|
return unmappedArguments;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public ReceiverValue getReceiverArgument() {
|
public ReceiverValue getReceiverArgument() {
|
||||||
@@ -250,4 +270,18 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
assert dataFlowInfo != null;
|
assert dataFlowInfo != null;
|
||||||
dataFlowInfo = dataFlowInfo.and(info);
|
dataFlowInfo = dataFlowInfo.and(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDeferredComputationForArgument(
|
||||||
|
@NotNull ValueArgument valueArgument,
|
||||||
|
@Nullable CallCandidateResolutionContext<FunctionDescriptor> callCandidateResolutionContext
|
||||||
|
) {
|
||||||
|
if (callCandidateResolutionContext != null) {
|
||||||
|
deferredComputationsForArguments.put(valueArgument, callCandidateResolutionContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public CallCandidateResolutionContext<FunctionDescriptor> getDeferredComputationForArgument(@NotNull ValueArgument valueArgument) {
|
||||||
|
return deferredComputationsForArguments.get(valueArgument);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package a
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
public fun <T> Iterable<T>.withIndices(): List<Pair<Int, T>> {
|
||||||
|
val answer = ArrayList<Pair<Int, T>>()
|
||||||
|
var nextIndex = 1
|
||||||
|
for (e in this) {
|
||||||
|
answer.add(Pair(nextIndex, e))
|
||||||
|
nextIndex++
|
||||||
|
}
|
||||||
|
return answer
|
||||||
|
}
|
||||||
|
|
||||||
|
//from standard library
|
||||||
|
public class Pair<out A, out B>(
|
||||||
|
public val first: A,
|
||||||
|
public val second: B
|
||||||
|
)
|
||||||
@@ -1993,7 +1993,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/inference")
|
@TestMetadata("compiler/testData/diagnostics/tests/inference")
|
||||||
@InnerTestClasses({Inference.Regressions.class, Inference.ReportingImprovements.class, Inference.UpperBounds.class, Inference.Varargs.class})
|
@InnerTestClasses({Inference.Complicated.class, Inference.Regressions.class, Inference.ReportingImprovements.class, Inference.UpperBounds.class, Inference.Varargs.class})
|
||||||
public static class Inference extends AbstractDiagnosticsTestWithEagerResolve {
|
public static class Inference extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
public void testAllFilesPresentInInference() throws Exception {
|
public void testAllFilesPresentInInference() throws Exception {
|
||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inference"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inference"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
@@ -2119,6 +2119,19 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/inference/typeInferenceExpectedTypeMismatch.kt");
|
doTest("compiler/testData/diagnostics/tests/inference/typeInferenceExpectedTypeMismatch.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/inference/complicated")
|
||||||
|
public static class Complicated extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
|
public void testAllFilesPresentInComplicated() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inference/complicated"), "kt", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("completeValueArgumentsInference.kt")
|
||||||
|
public void testCompleteValueArgumentsInference() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/inference/complicated/completeValueArgumentsInference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/regressions")
|
@TestMetadata("compiler/testData/diagnostics/tests/inference/regressions")
|
||||||
public static class Regressions extends AbstractDiagnosticsTestWithEagerResolve {
|
public static class Regressions extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
public void testAllFilesPresentInRegressions() throws Exception {
|
public void testAllFilesPresentInRegressions() throws Exception {
|
||||||
@@ -2399,6 +2412,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
public static Test innerSuite() {
|
public static Test innerSuite() {
|
||||||
TestSuite suite = new TestSuite("Inference");
|
TestSuite suite = new TestSuite("Inference");
|
||||||
suite.addTestSuite(Inference.class);
|
suite.addTestSuite(Inference.class);
|
||||||
|
suite.addTestSuite(Complicated.class);
|
||||||
suite.addTestSuite(Regressions.class);
|
suite.addTestSuite(Regressions.class);
|
||||||
suite.addTestSuite(ReportingImprovements.class);
|
suite.addTestSuite(ReportingImprovements.class);
|
||||||
suite.addTestSuite(UpperBounds.class);
|
suite.addTestSuite(UpperBounds.class);
|
||||||
|
|||||||
Reference in New Issue
Block a user