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) {
results = doResolveCall(context.replaceBindingTrace(traceToResolveCall), prioritizedTasks, callTransformer, reference);
if (results instanceof OverloadResolutionResultsImpl) {
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
OverloadResolutionResults<F> resultsWithFixedResolve = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
if (resultsWithFixedResolve instanceof OverloadResolutionResultsImpl) {
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) resultsWithFixedResolve).getTrace();
if (deltasTraceForTypeInference != null) {
deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
}
}
results = completeTypeInferenceDependentOnFunctionLiterals(newContext, resultsWithFixedResolve, TracingStrategy.EMPTY);
cacheResults(resolutionResultsSlice, context, results, traceToResolveCall);
}
@@ -297,6 +299,35 @@ public class CallResolver {
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(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResults<D> resultsWithIncompleteTypeInference,
@@ -306,38 +337,21 @@ public class CallResolver {
return resultsWithIncompleteTypeInference;
}
Set<ResolvedCallWithTrace<D>> candidates = Sets.newLinkedHashSet();
Set<ResolvedCallWithTrace<D>> incompleteCalls = Sets.newLinkedHashSet();
for (ResolvedCall<? extends D> cachedCall : resultsWithIncompleteTypeInference.getResultingCalls()) {
if (cachedCall instanceof ResolvedCallImpl) {
ResolvedCallImpl<D> resolvedCall = (ResolvedCallImpl<D>) cachedCall;
if (resolvedCall.hasUnknownTypeParameters()) {
ResolvedCallImpl<D> copy = CallResolverUtil.copy(resolvedCall, context);
incompleteCalls.add(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);
}
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);
}
}
else {
for (ResolvedCallWithTrace<D> callWithUnknownTypeParameters : incompleteCalls) {
ResolvedCallImpl<D> resolvedCall = (ResolvedCallImpl<D>) callWithUnknownTypeParameters;
resolvedCall.addStatus(ResolutionStatus.INCOMPLETE_TYPE_INFERENCE);
}
if (resultingCalls == null) {
resultingCalls = (Set<ResolvedCallWithTrace<D>>) resultsWithIncompleteTypeInference.getResultingCalls();
}
OverloadResolutionResultsImpl<D> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
context.trace, tracing, candidates);
context.trace, tracing, resultingCalls);
if (!results.isSingleResult()) {
argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
}
@@ -76,6 +76,7 @@ public class CallResolverUtil {
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : call.getValueArguments().entrySet()) {
copy.recordValueArgument(entry.getKey(), entry.getValue());
}
copy.setInitialDataFlowInfo(call.getDataFlowInfo());
return copy;
}
@@ -185,7 +185,7 @@ public class CandidateResolver {
return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
}
public <D extends CallableDescriptor> void completeTypeInferenceDependentOnExpectedTypeForCall(
public <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiteralsForCall(
CallCandidateResolutionContext<D, D> context
) {
ResolvedCallImpl<D> resolvedCall = context.candidateCall;
@@ -206,6 +206,16 @@ public class CandidateResolver {
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.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(),
@@ -65,11 +65,11 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor,
return create(candidateCall, task, trace, tracing, task.call);
}
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D, D> create(
@NotNull BasicCallResolutionContext context, @NotNull TracingStrategy tracing,
@NotNull ResolvedCallImpl<D> candidateCall) {
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D, D> createForCallBeingAnalyzed(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull BasicCallResolutionContext context, @NotNull TracingStrategy tracing
) {
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