separated addition of constraints for function literals(*) and for expected type

* = which argument types are known
  call with these function literal constraints is cached
This commit is contained in:
Svetlana Isakova
2013-01-31 15:26:52 +04:00
parent 9b2c666c1f
commit 3ef640039b
4 changed files with 61 additions and 36 deletions
@@ -276,13 +276,15 @@ public class CallResolver {
} }
} }
if (results == null) { if (results == null) {
results = doResolveCall(context.replaceBindingTrace(traceToResolveCall), prioritizedTasks, callTransformer, reference); BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
if (results instanceof OverloadResolutionResultsImpl) { OverloadResolutionResults<F> resultsWithFixedResolve = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace(); if (resultsWithFixedResolve instanceof OverloadResolutionResultsImpl) {
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) resultsWithFixedResolve).getTrace();
if (deltasTraceForTypeInference != null) { if (deltasTraceForTypeInference != null) {
deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall); deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
} }
} }
results = completeTypeInferenceDependentOnFunctionLiterals(newContext, resultsWithFixedResolve, TracingStrategy.EMPTY);
cacheResults(resolutionResultsSlice, context, results, traceToResolveCall); cacheResults(resolutionResultsSlice, context, results, traceToResolveCall);
} }
@@ -297,6 +299,35 @@ public class CallResolver {
return completeResults; return completeResults;
} }
private <D extends CallableDescriptor> OverloadResolutionResults<D> completeTypeInferenceDependentOnFunctionLiterals(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResults<D> resultsWithIncompleteTypeInference,
@NotNull TracingStrategy tracing
) {
if (resultsWithIncompleteTypeInference.getResultCode() != OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE) {
return resultsWithIncompleteTypeInference;
}
Set<ResolvedCallWithTrace<D>> candidates = Sets.newLinkedHashSet(
(Collection<? extends ResolvedCallWithTrace<D>>) resultsWithIncompleteTypeInference.getResultingCalls());
ResolvedCallWithTrace<D> maximallySpecific = OverloadingConflictResolver.INSTANCE.findMaximallySpecific(candidates, false);
if (maximallySpecific != null && maximallySpecific instanceof ResolvedCallImpl) {
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) {
ResolvedCallImpl<D> resolvedCall = (ResolvedCallImpl<D>) callWithUnknownTypeParameters;
resolvedCall.addStatus(ResolutionStatus.INCOMPLETE_TYPE_INFERENCE);
}
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> resultsWithIncompleteTypeInference,
@@ -306,38 +337,21 @@ public class CallResolver {
return resultsWithIncompleteTypeInference; return resultsWithIncompleteTypeInference;
} }
Set<ResolvedCallWithTrace<D>> candidates = Sets.newLinkedHashSet(); Set<ResolvedCallWithTrace<D>> resultingCalls = null;
Set<ResolvedCallWithTrace<D>> incompleteCalls = Sets.newLinkedHashSet(); if (resultsWithIncompleteTypeInference.isSingleResult()) {
for (ResolvedCall<? extends D> cachedCall : resultsWithIncompleteTypeInference.getResultingCalls()) { ResolvedCallWithTrace<D> resolvedCall = (ResolvedCallWithTrace<D>) resultsWithIncompleteTypeInference.getResultingCall();
if (cachedCall instanceof ResolvedCallImpl) { if (resolvedCall.hasUnknownTypeParameters() && resolvedCall instanceof ResolvedCallImpl) {
ResolvedCallImpl<D> resolvedCall = (ResolvedCallImpl<D>) cachedCall; ResolvedCallImpl<D> copy = CallResolverUtil.copy((ResolvedCallImpl<D>) resolvedCall, context);
if (resolvedCall.hasUnknownTypeParameters()) { candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(
ResolvedCallImpl<D> copy = CallResolverUtil.copy(resolvedCall, context); CallCandidateResolutionContext.createForCallBeingAnalyzed(copy, context, tracing));
incompleteCalls.add(copy); resultingCalls = Collections.<ResolvedCallWithTrace<D>>singleton(copy);
candidates.add(copy);
continue;
}
}
candidates.add((ResolvedCallWithTrace<D>) cachedCall);
}
ResolvedCallWithTrace<D> maximallySpecific = OverloadingConflictResolver.INSTANCE.findMaximallySpecific(incompleteCalls, false);
if (maximallySpecific != null) {
candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(
CallCandidateResolutionContext.create(context, tracing, (ResolvedCallImpl<D>) maximallySpecific));
for (ResolvedCallWithTrace<D> callWithUnknownTypeParameters : incompleteCalls) {
if (callWithUnknownTypeParameters != maximallySpecific) {
((ResolvedCallImpl<D>) callWithUnknownTypeParameters).addStatus(ResolutionStatus.OTHER_ERROR);
}
} }
} }
else { if (resultingCalls == null) {
for (ResolvedCallWithTrace<D> callWithUnknownTypeParameters : incompleteCalls) { resultingCalls = (Set<ResolvedCallWithTrace<D>>) resultsWithIncompleteTypeInference.getResultingCalls();
ResolvedCallImpl<D> resolvedCall = (ResolvedCallImpl<D>) callWithUnknownTypeParameters;
resolvedCall.addStatus(ResolutionStatus.INCOMPLETE_TYPE_INFERENCE);
}
} }
OverloadResolutionResultsImpl<D> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors( OverloadResolutionResultsImpl<D> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
context.trace, tracing, candidates); context.trace, tracing, resultingCalls);
if (!results.isSingleResult()) { if (!results.isSingleResult()) {
argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS); argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
} }
@@ -76,6 +76,7 @@ public class CallResolverUtil {
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : call.getValueArguments().entrySet()) { for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : call.getValueArguments().entrySet()) {
copy.recordValueArgument(entry.getKey(), entry.getValue()); copy.recordValueArgument(entry.getKey(), entry.getValue());
} }
copy.setInitialDataFlowInfo(call.getDataFlowInfo());
return copy; return copy;
} }
@@ -185,7 +185,7 @@ public class CandidateResolver {
return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null; return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
} }
public <D extends CallableDescriptor> void completeTypeInferenceDependentOnExpectedTypeForCall( public <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiteralsForCall(
CallCandidateResolutionContext<D, D> context CallCandidateResolutionContext<D, D> context
) { ) {
ResolvedCallImpl<D> resolvedCall = context.candidateCall; ResolvedCallImpl<D> resolvedCall = context.candidateCall;
@@ -206,6 +206,16 @@ public class CandidateResolver {
addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context); addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
} }
} }
}
public <D extends CallableDescriptor> void completeTypeInferenceDependentOnExpectedTypeForCall(
CallCandidateResolutionContext<D, D> context
) {
ResolvedCallImpl<D> resolvedCall = context.candidateCall;
assert resolvedCall.hasUnknownTypeParameters();
D descriptor = resolvedCall.getCandidateDescriptor();
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
assert constraintSystem != null;
ConstraintSystem constraintSystemWithoutExpectedTypeConstraint = constraintSystem.copy(); ConstraintSystem constraintSystemWithoutExpectedTypeConstraint = constraintSystem.copy();
constraintSystem.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(), constraintSystem.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(),
@@ -65,11 +65,11 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor,
return create(candidateCall, task, trace, tracing, task.call); return create(candidateCall, task, trace, tracing, task.call);
} }
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D, D> create( public static <D extends CallableDescriptor> CallCandidateResolutionContext<D, D> createForCallBeingAnalyzed(
@NotNull BasicCallResolutionContext context, @NotNull TracingStrategy tracing, @NotNull ResolvedCallImpl<D> candidateCall, @NotNull BasicCallResolutionContext context, @NotNull TracingStrategy tracing
@NotNull ResolvedCallImpl<D> candidateCall) { ) {
return new CallCandidateResolutionContext<D, D>(candidateCall, tracing, context.trace, context.scope, context.call, return new CallCandidateResolutionContext<D, D>(candidateCall, tracing, context.trace, context.scope, context.call,
context.expectedType, context.dataFlowInfo, context.namespacesAllowed, true); context.expectedType, context.dataFlowInfo, context.namespacesAllowed, false);
} }
@Override @Override