save explicitly 'INCOMPLETE_TYPE_INFERENCE' status

This commit is contained in:
Svetlana Isakova
2013-02-05 19:16:46 +04:00
parent 3f466e8aac
commit d09c5c5e5e
3 changed files with 43 additions and 31 deletions
@@ -27,9 +27,6 @@ import java.util.Collections;
public class OverloadResolutionResultsImpl<D extends CallableDescriptor> implements OverloadResolutionResults<D> {
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> success(@NotNull ResolvedCallWithTrace<D> candidate) {
if (candidate.hasUnknownTypeParameters()) {
return incompleteTypeInference(candidate);
}
return new OverloadResolutionResultsImpl<D>(Code.SUCCESS, Collections.singleton(candidate));
}
@@ -38,9 +35,6 @@ public class OverloadResolutionResultsImpl<D extends CallableDescriptor> impleme
}
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> singleFailedCandidate(ResolvedCallWithTrace<D> candidate) {
if (candidate.getStatus() != ResolutionStatus.STRONG_ERROR && candidate.hasUnknownTypeParameters()) {
return incompleteTypeInference(candidate);
}
return new OverloadResolutionResultsImpl<D>(Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH, Collections.singleton(candidate));
}
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> manyFailedCandidates(Collection<ResolvedCallWithTrace<D>> failedCandidates) {
@@ -48,11 +42,6 @@ public class OverloadResolutionResultsImpl<D extends CallableDescriptor> impleme
}
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> ambiguity(Collection<ResolvedCallWithTrace<D>> candidates) {
for (ResolvedCallWithTrace<D> candidate : candidates) {
if (candidate.hasUnknownTypeParameters()) {
return incompleteTypeInference(candidates);
}
}
return new OverloadResolutionResultsImpl<D>(Code.AMBIGUITY, candidates);
}
@@ -60,7 +49,7 @@ public class OverloadResolutionResultsImpl<D extends CallableDescriptor> impleme
return new OverloadResolutionResultsImpl<D>(Code.INCOMPLETE_TYPE_INFERENCE, candidates);
}
private static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> incompleteTypeInference(ResolvedCallWithTrace<D> candidate) {
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> incompleteTypeInference(ResolvedCallWithTrace<D> candidate) {
return incompleteTypeInference(Collections.singleton(candidate));
}
@@ -24,10 +24,7 @@ import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl.MAP_TO_CANDIDATE;
import static org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl.MAP_TO_RESULT;
@@ -73,28 +70,32 @@ public class ResolutionResultsHandler {
) {
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
if (successfulCandidates.size() > 0) {
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(successfulCandidates, true);
if (!successfulCandidates.isEmpty() || !incompleteCandidates.isEmpty()) {
Set<ResolvedCallWithTrace<D>> successfulAndIncomplete = Sets.newLinkedHashSet();
successfulAndIncomplete.addAll(successfulCandidates);
successfulAndIncomplete.addAll(incompleteCandidates);
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(successfulAndIncomplete, true);
if (results.isSingleResult()) {
results.getResultingCall().getTrace().moveAllMyDataTo(trace);
ResolvedCallWithTrace<D> resultingCall = results.getResultingCall();
resultingCall.getTrace().moveAllMyDataTo(trace);
if (resultingCall.getStatus() == INCOMPLETE_TYPE_INFERENCE) {
return OverloadResolutionResultsImpl.incompleteTypeInference(resultingCall);
}
}
if (results.isAmbiguity()) {
tracing.recordAmbiguity(trace, results.getResultingCalls());
if (allIncomplete(results.getResultingCalls())) {
tracing.cannotCompleteResolve(trace, results.getResultingCalls());
return OverloadResolutionResultsImpl.incompleteTypeInference(results.getResultingCalls());
}
// This check is needed for the following case:
// x.foo(unresolved) -- if there are multiple foo's, we'd report an ambiguity, and it does not make sense here
if (allClean(results.getResultingCalls())) {
tracing.ambiguity(trace, results.getResultingCalls());
}
tracing.recordAmbiguity(trace, results.getResultingCalls());
}
return results;
}
else if (!incompleteCandidates.isEmpty()) {
assert incompleteCandidates.size() > 1 :
"One incomplete candidate should have been chosen as maximally specific and completed earlier";
tracing.cannotCompleteResolve(trace, incompleteCandidates);
tracing.recordAmbiguity(trace, incompleteCandidates);
return OverloadResolutionResultsImpl.incompleteTypeInference(incompleteCandidates);
}
else if (!failedCandidates.isEmpty()) {
if (failedCandidates.size() != 1) {
// This is needed when there are several overloads some of which are OK but for nullability of the receiver,
@@ -142,13 +143,20 @@ public class ResolutionResultsHandler {
}
}
private <D extends CallableDescriptor> boolean allClean(Collection<ResolvedCallWithTrace<D>> results) {
private static <D extends CallableDescriptor> boolean allClean(@NotNull Collection<ResolvedCallWithTrace<D>> results) {
for (ResolvedCallWithTrace<D> result : results) {
if (result.isDirty()) return false;
}
return true;
}
private static <D extends CallableDescriptor> boolean allIncomplete(@NotNull Collection<ResolvedCallWithTrace<D>> results) {
for (ResolvedCallWithTrace<D> result : results) {
if (result.getStatus() != INCOMPLETE_TYPE_INFERENCE) return false;
}
return true;
}
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
@NotNull Set<ResolvedCallWithTrace<D>> candidates,
@@ -49,11 +49,26 @@ public enum ResolutionStatus {
}
public ResolutionStatus combine(ResolutionStatus other) {
if (this == UNKNOWN_STATUS || this.isSuccess()) return other;
if (!other.isSuccess() && this.getSeverityIndex() < other.getSeverityIndex()) return other;
if (this == UNKNOWN_STATUS) return other;
if (SUCCESS.among(this, other)) {
return SUCCESS.chooseDifferent(this, other);
}
if (INCOMPLETE_TYPE_INFERENCE.among(this, other)) {
return INCOMPLETE_TYPE_INFERENCE.chooseDifferent(this, other);
}
if (this.getSeverityIndex() < other.getSeverityIndex()) return other;
return this;
}
private boolean among(ResolutionStatus first, ResolutionStatus second) {
return this == first || this == second;
}
private ResolutionStatus chooseDifferent(ResolutionStatus first, ResolutionStatus second) {
assert among(first, second);
return this == first ? second : first;
}
private int getSeverityIndex() {
if (severityIndex == -1) {
for (int i = 0; i < SEVERITY_LEVELS.length; i++) {