diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt
index 1841ed6dfd7..b7615b955a2 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor
+import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver
/**
* For expressions like a(), a[i], a.b.c(), +a, a + b, (a()), a(): Int, @label a()
@@ -56,6 +57,16 @@ fun JetExpression.getCorrespondingCall(bindingContext: BindingContext): Call? {
return bindingContext[CALL, reference]
}
+fun Call.hasUnresolvedArguments(bindingContext: BindingContext): Boolean {
+ val arguments = getValueArguments().map { it?.getArgumentExpression() }
+ return arguments.any {
+ argument ->
+ val expressionType = bindingContext[BindingContext.EXPRESSION_TYPE, argument]
+ argument != null && !ArgumentTypeResolver.isFunctionLiteralArgument(argument)
+ && (expressionType == null || expressionType.isError())
+ }
+}
+
public fun JetReturnExpression.getTargetFunctionDescriptor(bindingContext: BindingContext): FunctionDescriptor? {
val targetLabel = getTargetLabel()
if (targetLabel != null) return bindingContext[LABEL_TARGET, targetLabel]?.let { bindingContext[FUNCTION, it] }
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 40f0b964d80..01236a192aa 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
@@ -566,7 +566,7 @@ public class CallResolver {
}
OverloadResolutionResultsImpl results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
- task.trace, task.tracing, task.getResolvedCalls());
+ task, task.getResolvedCalls());
if (!results.isSingleResult() && !results.isIncomplete()) {
argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
}
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
index f69c3474117..c7e679d5c05 100644
--- 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
@@ -19,13 +19,15 @@ 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.OverrideResolver;
+import org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage;
+import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
-import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
-import org.jetbrains.jet.lang.resolve.calls.util.UtilPackage;
+import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
-import java.util.*;
+import java.util.Collection;
+import java.util.EnumSet;
+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;
@@ -38,8 +40,7 @@ public class ResolutionResultsHandler {
@NotNull
public OverloadResolutionResultsImpl computeResultAndReportErrors(
- @NotNull BindingTrace trace,
- @NotNull TracingStrategy tracing,
+ @NotNull ResolutionTask task,
@NotNull Collection> candidates
) {
Set> successfulCandidates = Sets.newLinkedHashSet();
@@ -65,25 +66,24 @@ public class ResolutionResultsHandler {
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
if (!successfulCandidates.isEmpty() || !incompleteCandidates.isEmpty()) {
- return computeSuccessfulResult(trace, tracing, successfulCandidates, incompleteCandidates);
+ return computeSuccessfulResult(task, successfulCandidates, incompleteCandidates);
}
else if (!failedCandidates.isEmpty()) {
- return computeFailedResult(trace, tracing, failedCandidates);
+ return computeFailedResult(task, failedCandidates);
}
if (!candidatesWithWrongReceiver.isEmpty()) {
- tracing.unresolvedReferenceWrongReceiver(trace, candidatesWithWrongReceiver);
+ task.tracing.unresolvedReferenceWrongReceiver(task.trace, candidatesWithWrongReceiver);
return OverloadResolutionResultsImpl.candidatesWithWrongReceiver(candidatesWithWrongReceiver);
}
- tracing.unresolvedReference(trace);
+ task.tracing.unresolvedReference(task.trace);
return OverloadResolutionResultsImpl.nameNotFound();
}
@NotNull
private OverloadResolutionResultsImpl computeSuccessfulResult(
- BindingTrace trace,
- TracingStrategy tracing,
- Set> successfulCandidates,
- Set> incompleteCandidates
+ @NotNull ResolutionTask task,
+ @NotNull Set> successfulCandidates,
+ @NotNull Set> incompleteCandidates
) {
Set> successfulAndIncomplete = Sets.newLinkedHashSet();
successfulAndIncomplete.addAll(successfulCandidates);
@@ -91,21 +91,27 @@ public class ResolutionResultsHandler {
OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(successfulAndIncomplete, true);
if (results.isSingleResult()) {
MutableResolvedCall resultingCall = results.getResultingCall();
- resultingCall.getTrace().moveAllMyDataTo(trace);
+ resultingCall.getTrace().moveAllMyDataTo(task.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());
- }
+ task.tracing.recordAmbiguity(task.trace, results.getResultingCalls());
+ boolean allCandidatesIncomplete = allIncomplete(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());
+ if (task.checkArguments == CheckValueArgumentsMode.DISABLED ||
+ !BindingContextUtilPackage.hasUnresolvedArguments(task.call, task.trace.getBindingContext())) {
+ if (allCandidatesIncomplete) {
+ task.tracing.cannotCompleteResolve(task.trace, results.getResultingCalls());
+ }
+ else {
+ task.tracing.ambiguity(task.trace, results.getResultingCalls());
+ }
+ }
+ if (allCandidatesIncomplete) {
+ return OverloadResolutionResultsImpl.incompleteTypeInference(results.getResultingCalls());
}
}
return results;
@@ -113,9 +119,8 @@ public class ResolutionResultsHandler {
@NotNull
private OverloadResolutionResultsImpl computeFailedResult(
- BindingTrace trace,
- TracingStrategy tracing,
- Set> failedCandidates
+ @NotNull ResolutionTask task,
+ @NotNull Set> failedCandidates
) {
if (failedCandidates.size() != 1) {
// This is needed when there are several overloads some of which are OK but for nullability of the receiver,
@@ -131,12 +136,12 @@ public class ResolutionResultsHandler {
if (!thisLevel.isEmpty()) {
OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(thisLevel, false);
if (results.isSingleResult()) {
- results.getResultingCall().getTrace().moveAllMyDataTo(trace);
+ results.getResultingCall().getTrace().moveAllMyDataTo(task.trace);
return OverloadResolutionResultsImpl.singleFailedCandidate(results.getResultingCall());
}
- tracing.noneApplicable(trace, results.getResultingCalls());
- tracing.recordAmbiguity(trace, results.getResultingCalls());
+ task.tracing.noneApplicable(task.trace, results.getResultingCalls());
+ task.tracing.recordAmbiguity(task.trace, results.getResultingCalls());
return OverloadResolutionResultsImpl.manyFailedCandidates(results.getResultingCalls());
}
}
@@ -145,8 +150,8 @@ public class ResolutionResultsHandler {
Set> noOverrides = OverrideResolver.filterOutOverridden(failedCandidates, MAP_TO_CANDIDATE);
if (noOverrides.size() != 1) {
- tracing.noneApplicable(trace, noOverrides);
- tracing.recordAmbiguity(trace, noOverrides);
+ task.tracing.noneApplicable(task.trace, noOverrides);
+ task.tracing.recordAmbiguity(task.trace, noOverrides);
return OverloadResolutionResultsImpl.manyFailedCandidates(noOverrides);
}
@@ -154,17 +159,10 @@ public class ResolutionResultsHandler {
}
MutableResolvedCall failed = failedCandidates.iterator().next();
- failed.getTrace().moveAllMyDataTo(trace);
+ failed.getTrace().moveAllMyDataTo(task.trace);
return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
}
- private static boolean allClean(@NotNull Collection> results) {
- for (MutableResolvedCall result : results) {
- if (UtilPackage.isDirty(result)) return false;
- }
- return true;
- }
-
private static boolean allIncomplete(@NotNull Collection> results) {
for (MutableResolvedCall result : results) {
if (result.getStatus() != INCOMPLETE_TYPE_INFERENCE) return false;
@@ -181,24 +179,14 @@ public class ResolutionResultsHandler {
return OverloadResolutionResultsImpl.success(candidates.iterator().next());
}
- Set> cleanCandidates = Sets.newLinkedHashSet(candidates);
- for (Iterator> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) {
- MutableResolvedCall candidate = iterator.next();
- if (UtilPackage.isDirty(candidate)) {
- iterator.remove();
- }
- }
-
- if (cleanCandidates.isEmpty()) {
- cleanCandidates = candidates;
- }
- MutableResolvedCall maximallySpecific = OverloadingConflictResolver.INSTANCE.findMaximallySpecific(cleanCandidates, false);
+ MutableResolvedCall maximallySpecific = OverloadingConflictResolver.INSTANCE.findMaximallySpecific(candidates, false);
if (maximallySpecific != null) {
return OverloadResolutionResultsImpl.success(maximallySpecific);
}
if (discriminateGenerics) {
- MutableResolvedCall maximallySpecificGenericsDiscriminated = OverloadingConflictResolver.INSTANCE.findMaximallySpecific(cleanCandidates, true);
+ MutableResolvedCall maximallySpecificGenericsDiscriminated = OverloadingConflictResolver.INSTANCE.findMaximallySpecific(
+ candidates, true);
if (maximallySpecificGenericsDiscriminated != null) {
return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated);
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/resolvedCallUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/resolvedCallUtil.kt
index 371d2beb274..fa484ef4b93 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/resolvedCallUtil.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/resolvedCallUtil.kt
@@ -18,14 +18,10 @@ package org.jetbrains.jet.lang.resolve.calls.util
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
-import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentUnmapped
-import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument
-import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMapping
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMatch
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMatchStatus
-import java.util.ArrayList
import org.jetbrains.jet.lang.psi.Call
import org.jetbrains.jet.lang.psi.ValueArgument
@@ -52,15 +48,6 @@ public fun ResolvedCall.hasTypeMismatchErrorOnParame
}
}
-fun ResolvedCall.isDirty(): Boolean {
- return getValueArguments().values()
- .flatMap { it.getArguments() }
- .any { argument ->
- val argumentMapping = getArgumentMapping(argument)
- argumentMapping is ArgumentMatch && argumentMapping.status == ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE
- }
-}
-
fun Call.getAllValueArguments(): List {
val arguments = getValueArguments() +
getFunctionLiteralArguments().map { functionLiteral -> CallMaker.makeValueArgument(functionLiteral) }
diff --git a/compiler/testData/diagnostics/tests/incompleteCode/unresolvedArguments.kt b/compiler/testData/diagnostics/tests/incompleteCode/unresolvedArguments.kt
new file mode 100644
index 00000000000..a27667e5d69
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/incompleteCode/unresolvedArguments.kt
@@ -0,0 +1,12 @@
+//!DIAGNOSTICS: -UNUSED_PARAMETER
+
+fun foo(i: Int, t: T) {}
+fun foo(s: String, t: T) {}
+
+fun bar(i: Int) {}
+fun bar(s: String) {}
+
+fun test() {
+ foo(rrr, 1)
+ bar(rrr)
+}
diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java
index 3212c3fcc7c..022c1c99dcc 100644
--- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java
+++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java
@@ -3791,6 +3791,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/incompleteCode/typeParameterOnLhsOfDot.kt");
}
+ @TestMetadata("unresolvedArguments.kt")
+ public void testUnresolvedArguments() throws Exception {
+ doTest("compiler/testData/diagnostics/tests/incompleteCode/unresolvedArguments.kt");
+ }
+
@TestMetadata("variableDeclarationInSelector.kt")
public void testVariableDeclarationInSelector() throws Exception {
doTest("compiler/testData/diagnostics/tests/incompleteCode/variableDeclarationInSelector.kt");