diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java index b8289a677b2..a41141bb544 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java @@ -45,6 +45,8 @@ public class ResolutionResultsHandler { @NotNull ResolutionTask task, @NotNull Collection> candidates ) { + boolean resolveOverloads = task.checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS; // todo rename CheckArgumentTypesMode + Set> successfulCandidates = Sets.newLinkedHashSet(); Set> failedCandidates = Sets.newLinkedHashSet(); Set> incompleteCandidates = Sets.newLinkedHashSet(); @@ -68,10 +70,10 @@ 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(task, successfulCandidates, incompleteCandidates); + return computeSuccessfulResult(task, successfulCandidates, incompleteCandidates, resolveOverloads); } else if (!failedCandidates.isEmpty()) { - return computeFailedResult(task, failedCandidates); + return computeFailedResult(task, failedCandidates, resolveOverloads); } if (!candidatesWithWrongReceiver.isEmpty()) { task.tracing.unresolvedReferenceWrongReceiver(task.trace, candidatesWithWrongReceiver); @@ -85,12 +87,13 @@ public class ResolutionResultsHandler { private OverloadResolutionResultsImpl computeSuccessfulResult( @NotNull ResolutionTask task, @NotNull Set> successfulCandidates, - @NotNull Set> incompleteCandidates + @NotNull Set> incompleteCandidates, + boolean resolveOverloads ) { Set> successfulAndIncomplete = Sets.newLinkedHashSet(); successfulAndIncomplete.addAll(successfulCandidates); successfulAndIncomplete.addAll(incompleteCandidates); - OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(successfulAndIncomplete, true); + OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(successfulAndIncomplete, true, resolveOverloads); if (results.isSingleResult()) { MutableResolvedCall resultingCall = results.getResultingCall(); resultingCall.getTrace().moveAllMyDataTo(task.trace); @@ -122,7 +125,8 @@ public class ResolutionResultsHandler { @NotNull private OverloadResolutionResultsImpl computeFailedResult( @NotNull ResolutionTask task, - @NotNull Set> failedCandidates + @NotNull Set> failedCandidates, + boolean resolveOverloads ) { if (failedCandidates.size() != 1) { // This is needed when there are several overloads some of which are OK but for nullability of the receiver, @@ -139,7 +143,7 @@ public class ResolutionResultsHandler { if (severityLevel.contains(ARGUMENTS_MAPPING_ERROR)) { return recordFailedInfo(task, thisLevel); } - OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(thisLevel, false); + OverloadResolutionResultsImpl results = chooseAndReportMaximallySpecific(thisLevel, false, resolveOverloads); return recordFailedInfo(task, results.getResultingCalls()); } } @@ -178,7 +182,8 @@ public class ResolutionResultsHandler { @NotNull private OverloadResolutionResultsImpl chooseAndReportMaximallySpecific( @NotNull Set> candidates, - boolean discriminateGenerics + boolean discriminateGenerics, + boolean resolveOverloads ) { if (candidates.size() == 1) { return OverloadResolutionResultsImpl.success(candidates.iterator().next()); @@ -188,6 +193,9 @@ public class ResolutionResultsHandler { if (noOverrides.size() == 1) { return OverloadResolutionResultsImpl.success(noOverrides.iterator().next()); } + else if (!resolveOverloads) { + return OverloadResolutionResultsImpl.ambiguity(noOverrides); + } MutableResolvedCall maximallySpecific = overloadingConflictResolver.findMaximallySpecific(noOverrides, false); if (maximallySpecific != null) { diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/byGenericArgType.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/byGenericArgType.kt index 022437e419e..9c17a48e44b 100644 --- a/compiler/testData/diagnostics/tests/callableReference/resolve/byGenericArgType.kt +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/byGenericArgType.kt @@ -7,4 +7,4 @@ fun foo(s: String) {} val x1 = ofType<() -> Unit>(::foo) val x2 = ofType<(String) -> Unit>(::foo) -val x3 = ofType<(Int) -> Unit>(::foo) \ No newline at end of file +val x3 = ofType<(Int) -> Unit>(::foo) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/byValType.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/byValType.kt index c9e5829da61..4aa6dac8397 100644 --- a/compiler/testData/diagnostics/tests/callableReference/resolve/byValType.kt +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/byValType.kt @@ -3,7 +3,7 @@ fun foo() {} fun foo(s: String) {} -val x1 = ::foo +val x1 = ::foo val x2: () -> Unit = ::foo val x3: (String) -> Unit = ::foo -val x4: (Int) -> Unit = ::foo \ No newline at end of file +val x4: (Int) -> Unit = ::foo \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/byValType.txt b/compiler/testData/diagnostics/tests/callableReference/resolve/byValType.txt index 9d5d4b7b0a6..36af3186f98 100644 --- a/compiler/testData/diagnostics/tests/callableReference/resolve/byValType.txt +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/byValType.txt @@ -1,6 +1,6 @@ package -public val x1: kotlin.reflect.KFunction0 +public val x1: [ERROR : Type for ::foo] public val x2: () -> kotlin.Unit public val x3: (kotlin.String) -> kotlin.Unit public val x4: (kotlin.Int) -> kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.kt new file mode 100644 index 00000000000..008bd626354 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.kt @@ -0,0 +1,30 @@ +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION +import kotlin.reflect.KFunction1 + +open class A { + open fun bar() {} + + fun bas() {} +} +class B: A() { + override fun bar() {} + + fun bas(i: Int) {} +} + +fun A.foo() {} +fun B.foo() {} + +fun fas() {} +fun fas(i: Int = 1) {} + +fun test() { + B::foo // todo KT-9601 Chose maximally specific function in callable reference + + B::bar checkType { _>() } + + B::bas + + ::fas +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.txt b/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.txt new file mode 100644 index 00000000000..16c156f65bd --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/overloads.txt @@ -0,0 +1,26 @@ +package + +public fun fas(): kotlin.Unit +public fun fas(/*0*/ i: kotlin.Int = ...): kotlin.Unit +public fun test(): kotlin.Unit +public fun A.foo(): kotlin.Unit +public fun B.foo(): kotlin.Unit + +public open class A { + public constructor A() + public open fun bar(): kotlin.Unit + public final fun bas(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B : A { + public constructor B() + public open override /*1*/ fun bar(): kotlin.Unit + public final override /*1*/ /*fake_override*/ fun bas(): kotlin.Unit + public final fun bas(/*0*/ i: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.kt new file mode 100644 index 00000000000..6999d698730 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.kt @@ -0,0 +1,16 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION +// KT-9601 Chose maximally specific function in callable reference + +open class A { + fun foo(a: Any) {} + fun fas(a: Int) {} +} +class B: A() { + fun foo(a: Int) {} + fun fas(a: Any) {} +} + +fun test() { + B::foo + B::fas +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.txt b/compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.txt new file mode 100644 index 00000000000..b655b79a618 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.txt @@ -0,0 +1,23 @@ +package + +public fun test(): kotlin.Unit + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fas(/*0*/ a: kotlin.Int): kotlin.Unit + public final fun foo(/*0*/ a: kotlin.Any): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B : A { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun fas(/*0*/ a: kotlin.Any): kotlin.Unit + public final override /*1*/ /*fake_override*/ fun fas(/*0*/ a: kotlin.Int): kotlin.Unit + public final override /*1*/ /*fake_override*/ fun foo(/*0*/ a: kotlin.Any): kotlin.Unit + public final fun foo(/*0*/ a: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/withAs.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/withAs.kt index cafaae15a3f..ff34f30b9ea 100644 --- a/compiler/testData/diagnostics/tests/callableReference/resolve/withAs.kt +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/withAs.kt @@ -6,5 +6,5 @@ fun foo(s: String) {} fun bar(f: () -> Unit) = 1 fun bar(f: (String) -> Unit) = 2 -val x1 = ::foo as () -> Unit -val x2 = bar(::foo as (String) -> Unit) \ No newline at end of file +val x1 = ::foo as () -> Unit +val x2 = bar(::foo as (String) -> Unit) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.kt index e54c17dbfd8..6074d244a53 100644 --- a/compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.kt +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.kt @@ -6,5 +6,5 @@ fun foo(i: Int) {} val fn1: (Int) -> Unit = ::foo val fn2: (IntArray) -> Unit = ::foo -val fn3: (Int, Int) -> Unit = ::foo +val fn3: (Int, Int) -> Unit = ::foo val fn4: (Array) -> Unit = ::foo \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index cf1b999df95..c0f9426eec9 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -2015,6 +2015,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("overloads.kt") + public void testOverloads() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/overloads.kt"); + doTest(fileName); + } + + @TestMetadata("overloadsMember.kt") + public void testOverloadsMember() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.kt"); + doTest(fileName); + } + @TestMetadata("valVsFun.kt") public void testValVsFun() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/valVsFun.kt"); diff --git a/js/js.translator/testData/callableReference/property/cases/extensionProperty.kt b/js/js.translator/testData/callableReference/property/cases/extensionProperty.kt index d0dd6077d4c..ca7ddba8237 100644 --- a/js/js.translator/testData/callableReference/property/cases/extensionProperty.kt +++ b/js/js.translator/testData/callableReference/property/cases/extensionProperty.kt @@ -1,5 +1,6 @@ package foo +import kotlin.reflect.KMutableProperty1 open class A(var msg:String) { } @@ -21,7 +22,7 @@ fun box(): String { val a = A("Test") var refAExt = A::ext - var refBExt = B::ext + var refBExt: KMutableProperty1 = B::ext assertEquals("ext", refAExt.name) assertEquals("ext", refBExt.name)