diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 87463520df6..911fce1cecc 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.resolve.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler; import org.jetbrains.jet.lang.resolve.calls.results.OverloadingConflictResolver; import org.jetbrains.jet.lang.resolve.ImportsResolver; import org.jetbrains.jet.lang.resolve.ScriptHeaderResolver; @@ -85,6 +86,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private ExpressionTypingServices expressionTypingServices; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; + private ResolutionResultsHandler resolutionResultsHandler; private OverloadingConflictResolver overloadingConflictResolver; private ImportsResolver importsResolver; private ScriptHeaderResolver scriptHeaderResolver; @@ -133,6 +135,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.expressionTypingServices = new ExpressionTypingServices(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); + this.resolutionResultsHandler = new ResolutionResultsHandler(); this.overloadingConflictResolver = new OverloadingConflictResolver(); this.importsResolver = new ImportsResolver(); this.scriptHeaderResolver = new ScriptHeaderResolver(); @@ -215,7 +218,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly callResolver.setDescriptorResolver(descriptorResolver); callResolver.setExpressionTypingServices(expressionTypingServices); - callResolver.setOverloadingConflictResolver(overloadingConflictResolver); + callResolver.setResolutionResultsHandler(resolutionResultsHandler); callResolver.setTypeResolver(typeResolver); expressionTypingServices.setCallResolver(callResolver); @@ -228,6 +231,8 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly typeResolver.setModuleConfiguration(moduleConfiguration); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); + resolutionResultsHandler.setOverloadingConflictResolver(overloadingConflictResolver); + importsResolver.setConfiguration(moduleConfiguration); importsResolver.setContext(topDownAnalysisContext); importsResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java index a830cc44c0b..7524f66d23f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java @@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.resolve.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler; import org.jetbrains.jet.lang.resolve.calls.results.OverloadingConflictResolver; import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer; import org.jetbrains.jet.lang.resolve.DeclarationsChecker; @@ -52,6 +53,7 @@ public class InjectorForBodyResolve { private ExpressionTypingServices expressionTypingServices; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; + private ResolutionResultsHandler resolutionResultsHandler; private OverloadingConflictResolver overloadingConflictResolver; private ControlFlowAnalyzer controlFlowAnalyzer; private DeclarationsChecker declarationsChecker; @@ -77,6 +79,7 @@ public class InjectorForBodyResolve { this.expressionTypingServices = new ExpressionTypingServices(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); + this.resolutionResultsHandler = new ResolutionResultsHandler(); this.overloadingConflictResolver = new OverloadingConflictResolver(); this.controlFlowAnalyzer = new ControlFlowAnalyzer(); this.declarationsChecker = new DeclarationsChecker(); @@ -95,7 +98,7 @@ public class InjectorForBodyResolve { callResolver.setDescriptorResolver(descriptorResolver); callResolver.setExpressionTypingServices(expressionTypingServices); - callResolver.setOverloadingConflictResolver(overloadingConflictResolver); + callResolver.setResolutionResultsHandler(resolutionResultsHandler); callResolver.setTypeResolver(typeResolver); descriptorResolver.setAnnotationResolver(annotationResolver); @@ -115,6 +118,8 @@ public class InjectorForBodyResolve { typeResolver.setModuleConfiguration(moduleConfiguration); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); + resolutionResultsHandler.setOverloadingConflictResolver(overloadingConflictResolver); + controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters); controlFlowAnalyzer.setTrace(bindingTrace); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java index c797e475c76..242aa643e3d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; +import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler; import org.jetbrains.jet.lang.resolve.calls.results.OverloadingConflictResolver; import org.jetbrains.annotations.NotNull; import javax.annotation.PreDestroy; @@ -46,6 +47,7 @@ public class InjectorForLazyResolve { private AnnotationResolver annotationResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private CallResolver callResolver; + private ResolutionResultsHandler resolutionResultsHandler; private OverloadingConflictResolver overloadingConflictResolver; public InjectorForLazyResolve( @@ -65,6 +67,7 @@ public class InjectorForLazyResolve { this.annotationResolver = new AnnotationResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.callResolver = new CallResolver(); + this.resolutionResultsHandler = new ResolutionResultsHandler(); this.overloadingConflictResolver = new OverloadingConflictResolver(); this.descriptorResolver.setAnnotationResolver(annotationResolver); @@ -86,9 +89,11 @@ public class InjectorForLazyResolve { callResolver.setDescriptorResolver(descriptorResolver); callResolver.setExpressionTypingServices(expressionTypingServices); - callResolver.setOverloadingConflictResolver(overloadingConflictResolver); + callResolver.setResolutionResultsHandler(resolutionResultsHandler); callResolver.setTypeResolver(typeResolver); + resolutionResultsHandler.setOverloadingConflictResolver(overloadingConflictResolver); + } @PreDestroy diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java index ddfb92d7994..635ef5c643d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler; import org.jetbrains.jet.lang.resolve.calls.results.OverloadingConflictResolver; import org.jetbrains.annotations.NotNull; import javax.annotation.PreDestroy; @@ -40,6 +41,7 @@ public class InjectorForMacros { private AnnotationResolver annotationResolver; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; + private ResolutionResultsHandler resolutionResultsHandler; private OverloadingConflictResolver overloadingConflictResolver; public InjectorForMacros( @@ -54,6 +56,7 @@ public class InjectorForMacros { this.annotationResolver = new AnnotationResolver(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); + this.resolutionResultsHandler = new ResolutionResultsHandler(); this.overloadingConflictResolver = new OverloadingConflictResolver(); this.expressionTypingServices.setCallResolver(callResolver); @@ -63,7 +66,7 @@ public class InjectorForMacros { callResolver.setDescriptorResolver(descriptorResolver); callResolver.setExpressionTypingServices(expressionTypingServices); - callResolver.setOverloadingConflictResolver(overloadingConflictResolver); + callResolver.setResolutionResultsHandler(resolutionResultsHandler); callResolver.setTypeResolver(typeResolver); descriptorResolver.setAnnotationResolver(annotationResolver); @@ -78,6 +81,8 @@ public class InjectorForMacros { typeResolver.setModuleConfiguration(moduleConfiguration); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); + resolutionResultsHandler.setOverloadingConflictResolver(overloadingConflictResolver); + } @PreDestroy diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index c0f37fe1ff8..404c87a923f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.resolve.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler; import org.jetbrains.jet.lang.resolve.calls.results.OverloadingConflictResolver; import org.jetbrains.jet.lang.resolve.ImportsResolver; import org.jetbrains.jet.lang.resolve.ScriptHeaderResolver; @@ -68,6 +69,7 @@ public class InjectorForTopDownAnalyzerBasic { private ExpressionTypingServices expressionTypingServices; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; + private ResolutionResultsHandler resolutionResultsHandler; private OverloadingConflictResolver overloadingConflictResolver; private ImportsResolver importsResolver; private ScriptHeaderResolver scriptHeaderResolver; @@ -102,6 +104,7 @@ public class InjectorForTopDownAnalyzerBasic { this.expressionTypingServices = new ExpressionTypingServices(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); + this.resolutionResultsHandler = new ResolutionResultsHandler(); this.overloadingConflictResolver = new OverloadingConflictResolver(); this.importsResolver = new ImportsResolver(); this.scriptHeaderResolver = new ScriptHeaderResolver(); @@ -158,7 +161,7 @@ public class InjectorForTopDownAnalyzerBasic { callResolver.setDescriptorResolver(descriptorResolver); callResolver.setExpressionTypingServices(expressionTypingServices); - callResolver.setOverloadingConflictResolver(overloadingConflictResolver); + callResolver.setResolutionResultsHandler(resolutionResultsHandler); callResolver.setTypeResolver(typeResolver); expressionTypingServices.setCallResolver(callResolver); @@ -171,6 +174,8 @@ public class InjectorForTopDownAnalyzerBasic { typeResolver.setModuleConfiguration(moduleConfiguration); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); + resolutionResultsHandler.setOverloadingConflictResolver(overloadingConflictResolver); + importsResolver.setConfiguration(moduleConfiguration); importsResolver.setContext(topDownAnalysisContext); importsResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 9c79e23be73..2114a2744ab 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -61,8 +61,6 @@ import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*; -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; import static org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData.ExtendedInferenceErrorData; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; @@ -74,7 +72,7 @@ public class CallResolver { private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE; @NotNull - private OverloadingConflictResolver overloadingConflictResolver; + private ResolutionResultsHandler resolutionResultsHandler; @NotNull private ExpressionTypingServices expressionTypingServices; @NotNull @@ -82,10 +80,9 @@ public class CallResolver { @NotNull private DescriptorResolver descriptorResolver; - @Inject - public void setOverloadingConflictResolver(@NotNull OverloadingConflictResolver overloadingConflictResolver) { - this.overloadingConflictResolver = overloadingConflictResolver; + public void setResolutionResultsHandler(@NotNull ResolutionResultsHandler resolutionResultsHandler) { + this.resolutionResultsHandler = resolutionResultsHandler; } @Inject @@ -342,7 +339,8 @@ public class CallResolver { } completeTypeInferenceDependentOnExpectedTypeForCall(CallResolutionContext.create(context, tracing, resolvedCall), successful, failed); } - OverloadResolutionResultsImpl results = computeResultAndReportErrors(context.trace, tracing, successful, failed); + OverloadResolutionResultsImpl results = resolutionResultsHandler.computeResultAndReportErrors(context.trace, tracing, successful, + failed); if (!results.isSingleResult()) { checkTypesWithNoCallee(context); } @@ -612,8 +610,9 @@ public class CallResolver { } } - OverloadResolutionResultsImpl results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, - failedCandidates); + OverloadResolutionResultsImpl results = resolutionResultsHandler.computeResultAndReportErrors(task.trace, task.tracing, + successfulCandidates, + failedCandidates); if (!results.isSingleResult() && !results.isIncomplete()) { checkTypesWithNoCallee(task.toBasic()); } @@ -1033,122 +1032,6 @@ public class CallResolver { } } - @NotNull - private OverloadResolutionResultsImpl computeResultAndReportErrors( - @NotNull BindingTrace trace, - @NotNull TracingStrategy tracing, - @NotNull Set> successfulCandidates, - @NotNull Set> failedCandidates) { - // TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific - - if (successfulCandidates.size() > 0) { - OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(successfulCandidates, true); - if (results.isSingleResult()) { - results.getResultingCall().getTrace().moveAllMyDataTo(trace); - } - if (results.isAmbiguity()) { - // 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 (!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, - // and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable" - // Used to be: weak errors. Generalized for future extensions - for (EnumSet severityLevel : SEVERITY_LEVELS) { - Set> thisLevel = Sets.newLinkedHashSet(); - for (ResolvedCallWithTrace candidate : failedCandidates) { - if (severityLevel.contains(candidate.getStatus())) { - thisLevel.add(candidate); - } - } - if (!thisLevel.isEmpty()) { - OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(thisLevel, false); - if (results.isSingleResult()) { - results.getResultingCall().getTrace().moveAllMyDataTo(trace); - return OverloadResolutionResultsImpl.singleFailedCandidate(results.getResultingCall()); - } - - tracing.noneApplicable(trace, results.getResultingCalls()); - tracing.recordAmbiguity(trace, results.getResultingCalls()); - return OverloadResolutionResultsImpl.manyFailedCandidates(results.getResultingCalls()); - } - } - - assert false : "Should not be reachable, cause every status must belong to some level"; - - Set> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE); - if (noOverrides.size() != 1) { - tracing.noneApplicable(trace, noOverrides); - tracing.recordAmbiguity(trace, noOverrides); - return OverloadResolutionResultsImpl.manyFailedCandidates(noOverrides); - } - - failedCandidates = noOverrides; - } - - ResolvedCallWithTrace failed = failedCandidates.iterator().next(); - failed.getTrace().moveAllMyDataTo(trace); - return OverloadResolutionResultsImpl.singleFailedCandidate(failed); - } - else { - tracing.unresolvedReference(trace); - return OverloadResolutionResultsImpl.nameNotFound(); - } - } - - private static boolean allClean(Collection> results) { - for (ResolvedCallWithTrace result : results) { - if (result.isDirty()) return false; - } - return true; - } - - private OverloadResolutionResultsImpl chooseAndReportMaximallySpecific( - @NotNull Set> candidates, - boolean discriminateGenerics - ) { - if (candidates.size() != 1) { - Set> cleanCandidates = Sets.newLinkedHashSet(candidates); - for (Iterator> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) { - ResolvedCallWithTrace candidate = iterator.next(); - if (candidate.isDirty()) { - iterator.remove(); - } - } - - if (cleanCandidates.isEmpty()) { - cleanCandidates = candidates; - } - ResolvedCallWithTrace maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false); - if (maximallySpecific != null) { - return OverloadResolutionResultsImpl.success(maximallySpecific); - } - - if (discriminateGenerics) { - ResolvedCallWithTrace maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true); - if (maximallySpecificGenericsDiscriminated != null) { - return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated); - } - } - - Set> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT); - - return OverloadResolutionResultsImpl.ambiguity(noOverrides); - } - else { - ResolvedCallWithTrace result = candidates.iterator().next(); - - return OverloadResolutionResultsImpl.success(result); - } - } - private void checkGenericBoundsInAFunctionCall(List jetTypeArguments, List typeArguments, CallableDescriptor functionDescriptor, BindingTrace trace) { Map context = Maps.newHashMap(); @@ -1181,7 +1064,8 @@ public class CallResolver { ResolvedCallImpl call = ResolvedCallImpl.create(candidate, temporaryBindingTrace); calls.add(call); } - return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.>emptySet()); + return resolutionResultsHandler.computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, + Collections.>emptySet()); } private List> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/ResolutionResultsHandler.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/ResolutionResultsHandler.java new file mode 100644 index 00000000000..868a819c89f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/ResolutionResultsHandler.java @@ -0,0 +1,164 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.calls.results; + +import com.google.common.collect.Sets; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.resolve.BindingTrace; +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 javax.inject.Inject; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Set; + +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; +import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.SEVERITY_LEVELS; + +public class ResolutionResultsHandler { + @NotNull + private OverloadingConflictResolver overloadingConflictResolver; + + @Inject + public void setOverloadingConflictResolver(@NotNull OverloadingConflictResolver overloadingConflictResolver) { + this.overloadingConflictResolver = overloadingConflictResolver; + } + + @NotNull + public OverloadResolutionResultsImpl computeResultAndReportErrors( + @NotNull BindingTrace trace, + @NotNull TracingStrategy tracing, + @NotNull Set> successfulCandidates, + @NotNull Set> failedCandidates) { + // TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific + + if (successfulCandidates.size() > 0) { + OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(successfulCandidates, true); + if (results.isSingleResult()) { + results.getResultingCall().getTrace().moveAllMyDataTo(trace); + } + if (results.isAmbiguity()) { + // 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 (!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, + // and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable" + // Used to be: weak errors. Generalized for future extensions + for (EnumSet severityLevel : SEVERITY_LEVELS) { + Set> thisLevel = Sets.newLinkedHashSet(); + for (ResolvedCallWithTrace candidate : failedCandidates) { + if (severityLevel.contains(candidate.getStatus())) { + thisLevel.add(candidate); + } + } + if (!thisLevel.isEmpty()) { + OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(thisLevel, false); + if (results.isSingleResult()) { + results.getResultingCall().getTrace().moveAllMyDataTo(trace); + return OverloadResolutionResultsImpl.singleFailedCandidate(results.getResultingCall()); + } + + tracing.noneApplicable(trace, results.getResultingCalls()); + tracing.recordAmbiguity(trace, results.getResultingCalls()); + return OverloadResolutionResultsImpl.manyFailedCandidates(results.getResultingCalls()); + } + } + + assert false : "Should not be reachable, cause every status must belong to some level"; + + Set> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE); + if (noOverrides.size() != 1) { + tracing.noneApplicable(trace, noOverrides); + tracing.recordAmbiguity(trace, noOverrides); + return OverloadResolutionResultsImpl.manyFailedCandidates(noOverrides); + } + + failedCandidates = noOverrides; + } + + ResolvedCallWithTrace failed = failedCandidates.iterator().next(); + failed.getTrace().moveAllMyDataTo(trace); + return OverloadResolutionResultsImpl.singleFailedCandidate(failed); + } + else { + tracing.unresolvedReference(trace); + return OverloadResolutionResultsImpl.nameNotFound(); + } + } + + private static boolean allClean(Collection> results) { + for (ResolvedCallWithTrace result : results) { + if (result.isDirty()) return false; + } + return true; + } + + @NotNull + private OverloadResolutionResultsImpl chooseAndReportMaximallySpecific( + @NotNull Set> candidates, + boolean discriminateGenerics + ) { + if (candidates.size() != 1) { + Set> cleanCandidates = Sets.newLinkedHashSet(candidates); + for (Iterator> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) { + ResolvedCallWithTrace candidate = iterator.next(); + if (candidate.isDirty()) { + iterator.remove(); + } + } + + if (cleanCandidates.isEmpty()) { + cleanCandidates = candidates; + } + ResolvedCallWithTrace maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false); + if (maximallySpecific != null) { + return OverloadResolutionResultsImpl.success(maximallySpecific); + } + + if (discriminateGenerics) { + ResolvedCallWithTrace maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true); + if (maximallySpecificGenericsDiscriminated != null) { + return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated); + } + } + + Set> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT); + + return OverloadResolutionResultsImpl.ambiguity(noOverrides); + } + else { + ResolvedCallWithTrace result = candidates.iterator().next(); + + return OverloadResolutionResultsImpl.success(result); + } + } + + +} diff --git a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java index 50d7cf4806c..921615c1546 100644 --- a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java +++ b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java @@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.ModuleConfiguration; import com.intellij.openapi.project.Project; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler; import org.jetbrains.jet.lang.resolve.calls.results.OverloadingConflictResolver; import org.jetbrains.annotations.NotNull; import javax.annotation.PreDestroy; @@ -42,6 +43,7 @@ public class InjectorForTests { private final Project project; private AnnotationResolver annotationResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; + private ResolutionResultsHandler resolutionResultsHandler; private OverloadingConflictResolver overloadingConflictResolver; public InjectorForTests( @@ -56,6 +58,7 @@ public class InjectorForTests { this.project = project; this.annotationResolver = new AnnotationResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); + this.resolutionResultsHandler = new ResolutionResultsHandler(); this.overloadingConflictResolver = new OverloadingConflictResolver(); this.descriptorResolver.setAnnotationResolver(annotationResolver); @@ -74,12 +77,14 @@ public class InjectorForTests { this.callResolver.setDescriptorResolver(descriptorResolver); this.callResolver.setExpressionTypingServices(expressionTypingServices); - this.callResolver.setOverloadingConflictResolver(overloadingConflictResolver); + this.callResolver.setResolutionResultsHandler(resolutionResultsHandler); this.callResolver.setTypeResolver(typeResolver); annotationResolver.setCallResolver(callResolver); annotationResolver.setExpressionTypingServices(expressionTypingServices); + resolutionResultsHandler.setOverloadingConflictResolver(overloadingConflictResolver); + } @PreDestroy diff --git a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 31969c89119..d4439f033a3 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.resolve.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler; import org.jetbrains.jet.lang.resolve.calls.results.OverloadingConflictResolver; import org.jetbrains.jet.lang.resolve.ImportsResolver; import org.jetbrains.jet.lang.resolve.ScriptHeaderResolver; @@ -68,6 +69,7 @@ public class InjectorForTopDownAnalyzerForJs { private ExpressionTypingServices expressionTypingServices; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; + private ResolutionResultsHandler resolutionResultsHandler; private OverloadingConflictResolver overloadingConflictResolver; private ImportsResolver importsResolver; private ScriptHeaderResolver scriptHeaderResolver; @@ -102,6 +104,7 @@ public class InjectorForTopDownAnalyzerForJs { this.expressionTypingServices = new ExpressionTypingServices(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); + this.resolutionResultsHandler = new ResolutionResultsHandler(); this.overloadingConflictResolver = new OverloadingConflictResolver(); this.importsResolver = new ImportsResolver(); this.scriptHeaderResolver = new ScriptHeaderResolver(); @@ -158,7 +161,7 @@ public class InjectorForTopDownAnalyzerForJs { callResolver.setDescriptorResolver(descriptorResolver); callResolver.setExpressionTypingServices(expressionTypingServices); - callResolver.setOverloadingConflictResolver(overloadingConflictResolver); + callResolver.setResolutionResultsHandler(resolutionResultsHandler); callResolver.setTypeResolver(typeResolver); expressionTypingServices.setCallResolver(callResolver); @@ -171,6 +174,8 @@ public class InjectorForTopDownAnalyzerForJs { typeResolver.setModuleConfiguration(moduleConfiguration); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); + resolutionResultsHandler.setOverloadingConflictResolver(overloadingConflictResolver); + importsResolver.setConfiguration(moduleConfiguration); importsResolver.setContext(topDownAnalysisContext); importsResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);