Filter out equivalent calls before reporting "none applicable"

If a module is configured in such a way that the same function appears multiple
times via different dependencies, it's not helpful to report "none of the
following functions can be called", listing the same function multiple times
This commit is contained in:
Alexander Udalov
2016-09-29 12:44:23 +03:00
parent 5d37fab4f5
commit 610c549225
5 changed files with 56 additions and 4 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
import java.util.Collection;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.Set;
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.*;
@@ -147,7 +148,9 @@ public class ResolutionResultsHandler {
}
if (!thisLevel.isEmpty()) {
if (severityLevel.contains(ARGUMENTS_MAPPING_ERROR)) {
return recordFailedInfo(tracing, trace, thisLevel);
@SuppressWarnings("unchecked")
OverloadingConflictResolver<MutableResolvedCall<D>> myResolver = (OverloadingConflictResolver) overloadingConflictResolver;
return recordFailedInfo(tracing, trace, myResolver.filterOutEquivalentCalls(new LinkedHashSet<MutableResolvedCall<D>>(thisLevel)));
}
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false, false, checkArgumentsMode);
return recordFailedInfo(tracing, trace, results.getResultingCalls());
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import java.lang.AssertionError
import java.util.*
class OverloadingConflictResolver<C : Any>(
@@ -94,8 +93,7 @@ class OverloadingConflictResolver<C : Any>(
// Sometimes we should compare "copies" from sources and from binary files.
// But we cannot compare return types for such copies, because it may lead us to recursive problem (see KT-11995).
// Because of this we compare them without return type and choose descriptor from source if we found duplicate.
private fun filterOutEquivalentCalls(
candidates: Set<C>): Set<C> {
fun filterOutEquivalentCalls(candidates: Set<C>): Set<C> {
if (candidates.size <= 1) return candidates
val fromSourcesGoesFirst = candidates.sortedBy { if (isFromSources(it.resultingDescriptor)) 0 else 1 }
@@ -0,0 +1,20 @@
// MODULE: m1
// FILE: a.kt
package p
fun f(s: String, t: String) = s + t
// MODULE: m2
// FILE: b.kt
package p
fun f(s: String, t: String) = t + s
// MODULE: m3(m1, m2)
// FILE: c.kt
import p.f
fun test() {
// There should be no "none applicable" error here
f(
<!SYNTAX!><!>}
@@ -0,0 +1,25 @@
// -- Module: <m1> --
package
package p {
public fun f(/*0*/ s: kotlin.String, /*1*/ t: kotlin.String): kotlin.String
}
// -- Module: <m2> --
package
package p {
public fun f(/*0*/ s: kotlin.String, /*1*/ t: kotlin.String): kotlin.String
}
// -- Module: <m3> --
package
public fun test(): kotlin.Unit
package p {
public fun f(/*0*/ s: kotlin.String, /*1*/ t: kotlin.String): kotlin.String
public fun f(/*0*/ s: kotlin.String, /*1*/ t: kotlin.String): kotlin.String
}
@@ -12311,6 +12311,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("incompleteCodeNoNoneApplicable.kt")
public void testIncompleteCodeNoNoneApplicable() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multimodule/duplicateMethod/incompleteCodeNoNoneApplicable.kt");
doTest(fileName);
}
@TestMetadata("noGenericsInParams.kt")
public void testNoGenericsInParams() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multimodule/duplicateMethod/noGenericsInParams.kt");