cache resolve results for incomplete type inference

This commit is contained in:
Svetlana Isakova
2012-10-23 15:45:17 +04:00
parent 3260a5a32c
commit 1f9d08861d
2 changed files with 48 additions and 46 deletions
@@ -274,43 +274,37 @@ public class CallResolver {
@NotNull CallTransformer<D, F> callTransformer, @NotNull CallTransformer<D, F> callTransformer,
@NotNull final JetReferenceExpression reference) { @NotNull final JetReferenceExpression reference) {
PsiElement element = context.call.getCallElement(); PsiElement element = context.call.getCallElement();
OverloadResolutionResults<F> results = null;
TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
if (element instanceof JetExpression) { if (element instanceof JetExpression) {
OverloadResolutionResults<F> cachedResults = context.trace.get(resolutionResultsSlice, CallKey.create(context.call.getCallType(), (JetExpression) element)); CallKey key = CallKey.create(context.call.getCallType(), (JetExpression) element);
OverloadResolutionResults<F> cachedResults = context.trace.get(resolutionResultsSlice, key);
if (cachedResults != null) { if (cachedResults != null) {
DelegatingBindingTrace delegatingTrace = context.trace.get(TRACE_DELTAS_CACHE, (JetExpression) element); DelegatingBindingTrace deltasTraceForResolve = context.trace.get(TRACE_DELTAS_CACHE, (JetExpression) element);
assert delegatingTrace != null; assert deltasTraceForResolve != null;
delegatingTrace.addAllMyDataTo(context.trace); deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
return cachedResults; results = cachedResults;
} }
} }
TemporaryBindingTrace delegatingBindingTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call); if (results == null) {
BasicResolutionContext newContext = context.replaceTrace(delegatingBindingTrace); results = doResolveCall(context.replaceTrace(traceToResolveCall), prioritizedTasks, callTransformer, reference);
OverloadResolutionResults<F> results = doResolveCall(newContext, if (results instanceof OverloadResolutionResultsImpl) {
prioritizedTasks, DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
callTransformer, reference); if (deltasTraceForTypeInference != null) {
DelegatingBindingTrace cloneDelta = new DelegatingBindingTrace( deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
new BindingTraceContext().getBindingContext(), "delta trace for caching resolve of", context.call); }
delegatingBindingTrace.addAllMyDataTo(cloneDelta); }
cacheResults(resolutionResultsSlice, context, results, cloneDelta); cacheResults(resolutionResultsSlice, context, results, traceToResolveCall);
}
if (prioritizedTasks.isEmpty()) { if (prioritizedTasks.isEmpty()) {
delegatingBindingTrace.commit(); traceToResolveCall.commit();
return results; return results;
} }
TemporaryBindingTrace temporaryBindingTrace = null;
if (results instanceof OverloadResolutionResultsImpl) {
temporaryBindingTrace = ((OverloadResolutionResultsImpl) results).getTrace();
if (temporaryBindingTrace != null) {
newContext = newContext.replaceTrace(temporaryBindingTrace);
}
}
TracingStrategy tracing = prioritizedTasks.iterator().next().tracing; TracingStrategy tracing = prioritizedTasks.iterator().next().tracing;
OverloadResolutionResults<F> completeResults = completeTypeInferenceDependentOnExpectedType(newContext, results, tracing); OverloadResolutionResults<F> completeResults = completeTypeInferenceDependentOnExpectedType(
if (temporaryBindingTrace != null) { context.replaceTrace(traceToResolveCall), results, tracing);
temporaryBindingTrace.commit(); traceToResolveCall.commit();
}
delegatingBindingTrace.commit();
return completeResults; return completeResults;
} }
@@ -319,12 +313,13 @@ public class CallResolver {
@NotNull OverloadResolutionResults<D> resultsWithIncompleteTypeInference, @NotNull OverloadResolutionResults<D> resultsWithIncompleteTypeInference,
@NotNull TracingStrategy tracing @NotNull TracingStrategy tracing
) { ) {
if (resultsWithIncompleteTypeInference.getResultCode() != OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE) return resultsWithIncompleteTypeInference; if (resultsWithIncompleteTypeInference.getResultCode() != OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE)
return resultsWithIncompleteTypeInference;
Set<ResolvedCallWithTrace<D>> successful = Sets.newLinkedHashSet(); Set<ResolvedCallWithTrace<D>> successful = Sets.newLinkedHashSet();
Set<ResolvedCallWithTrace<D>> failed = Sets.newLinkedHashSet(); Set<ResolvedCallWithTrace<D>> failed = Sets.newLinkedHashSet();
for (ResolvedCall<? extends D> call : resultsWithIncompleteTypeInference.getResultingCalls()) { for (ResolvedCall<? extends D> call : resultsWithIncompleteTypeInference.getResultingCalls()) {
if (!(call instanceof ResolvedCallImpl)) continue; if (!(call instanceof ResolvedCallImpl)) continue;
ResolvedCallImpl<D> resolvedCall = (ResolvedCallImpl<D>) call; ResolvedCallImpl<D> resolvedCall = ((ResolvedCallImpl<D>) call).copy(context);
if (!resolvedCall.hasUnknownTypeParameters()) { if (!resolvedCall.hasUnknownTypeParameters()) {
if (resolvedCall.getStatus().isSuccess()) { if (resolvedCall.getStatus().isSuccess()) {
successful.add(resolvedCall); successful.add(resolvedCall);
@@ -388,9 +383,10 @@ public class CallResolver {
List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, resolvedCall.getTrace()).argumentTypes; List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, resolvedCall.getTrace()).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(resolvedCall.getTrace(),
InferenceErrorData InferenceErrorData
.create(descriptor, constraintSystem, argumentTypes, receiverType, context.expectedType), .create(descriptor, constraintSystem, argumentTypes, receiverType,
constraintSystemWithoutExpectedTypeConstraint); context.expectedType),
constraintSystemWithoutExpectedTypeConstraint);
resolvedCall.addStatus(ResolutionStatus.TYPE_INFERENCE_ERROR); resolvedCall.addStatus(ResolutionStatus.TYPE_INFERENCE_ERROR);
failed.add(resolvedCall); failed.add(resolvedCall);
return; return;
@@ -426,19 +422,24 @@ public class CallResolver {
private <F extends CallableDescriptor> void cacheResults(@NotNull WritableSlice<CallKey, OverloadResolutionResults<F>> resolutionResultsSlice, private <F extends CallableDescriptor> void cacheResults(@NotNull WritableSlice<CallKey, OverloadResolutionResults<F>> resolutionResultsSlice,
@NotNull BasicResolutionContext context, @NotNull OverloadResolutionResults<F> results, @NotNull BasicResolutionContext context, @NotNull OverloadResolutionResults<F> results,
@NotNull DelegatingBindingTrace delegatingBindingTrace) { @NotNull DelegatingBindingTrace traceToResolveCall) {
boolean canBeCached = true; //boolean canBeCached = true;
for (ResolvedCall<? extends CallableDescriptor> call : results.getResultingCalls()) { //for (ResolvedCall<? extends CallableDescriptor> call : results.getResultingCalls()) {
if (!call.getCandidateDescriptor().getTypeParameters().isEmpty()) { // if (!call.getCandidateDescriptor().getTypeParameters().isEmpty()) {
canBeCached = false; // canBeCached = false;
} // }
} //}
if (!canBeCached) return; //if (!canBeCached) return;
PsiElement callElement = context.call.getCallElement(); PsiElement callElement = context.call.getCallElement();
if (!(callElement instanceof JetExpression)) return; if (!(callElement instanceof JetExpression)) return;
DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
new BindingTraceContext().getBindingContext(), "delta trace for caching resolve of", context.call);
traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
context.trace.record(resolutionResultsSlice, CallKey.create(context.call.getCallType(), (JetExpression)callElement), results); context.trace.record(resolutionResultsSlice, CallKey.create(context.call.getCallType(), (JetExpression)callElement), results);
context.trace.record(TRACE_DELTAS_CACHE, (JetExpression) callElement, delegatingBindingTrace); context.trace.record(TRACE_DELTAS_CACHE, (JetExpression) callElement, deltasTraceToCacheResolve);
} }
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) { private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) {
@@ -557,7 +558,7 @@ public class CallResolver {
for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) { for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create( TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
task.trace, "trace to resolve candidate", resolutionCandidate); task.trace, "trace to resolve candidate");
Collection<CallResolutionContext<D, F>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace); Collection<CallResolutionContext<D, F>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
for (CallResolutionContext<D, F> context : contexts) { for (CallResolutionContext<D, F> context : contexts) {
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import java.util.Collection; import java.util.Collection;
@@ -68,7 +69,7 @@ import java.util.Collections;
private final Collection<ResolvedCallWithTrace<D>> results; private final Collection<ResolvedCallWithTrace<D>> results;
private final Code resultCode; private final Code resultCode;
private TemporaryBindingTrace trace; private DelegatingBindingTrace trace;
private OverloadResolutionResultsImpl(@NotNull Code resultCode, @NotNull Collection<ResolvedCallWithTrace<D>> results) { private OverloadResolutionResultsImpl(@NotNull Code resultCode, @NotNull Collection<ResolvedCallWithTrace<D>> results) {
this.results = results; this.results = results;
@@ -130,11 +131,11 @@ import java.util.Collections;
// return new OverloadResolutionResultsImpl<D>(resultCode, functionDescriptors); // return new OverloadResolutionResultsImpl<D>(resultCode, functionDescriptors);
// } // }
public TemporaryBindingTrace getTrace() { public DelegatingBindingTrace getTrace() {
return trace; return trace;
} }
public OverloadResolutionResultsImpl<D> setTrace(TemporaryBindingTrace trace) { public OverloadResolutionResultsImpl<D> setTrace(DelegatingBindingTrace trace) {
this.trace = trace; this.trace = trace;
return this; return this;
} }