diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java index 6e6daf6dd74..91d179bd635 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java @@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; +import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; @@ -69,16 +70,38 @@ public class OverloadingConflictResolver { boolean discriminateGenericDescriptors ) { D me = candidateCall.getResultingDescriptor(); + + boolean isInvoke = candidateCall instanceof VariableAsFunctionResolvedCall; + VariableDescriptor variable; + if (isInvoke) { + variable = ((VariableAsFunctionResolvedCall) candidateCall).getVariableCall().getResultingDescriptor(); + } + else { + variable = null; + } + for (ResolvedCallWithTrace otherCall : candidates) { D other = otherCall.getResultingDescriptor(); if (other == me) continue; - if (!moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors)) { - return false; + + if (definitelyNotMaximallySpecific(me, other, discriminateGenericDescriptors)) { + + if (!isInvoke) return false; + + assert otherCall instanceof VariableAsFunctionResolvedCall : "'invoke' candidate goes with usual one: " + candidateCall + otherCall; + ResolvedCallWithTrace otherVariableCall = ((VariableAsFunctionResolvedCall) otherCall).getVariableCall(); + if (definitelyNotMaximallySpecific(variable, otherVariableCall.getResultingDescriptor(), discriminateGenericDescriptors)) { + return false; + } } } return true; } + private boolean definitelyNotMaximallySpecific(D me, D other, boolean discriminateGenericDescriptors) { + return !moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors); + } + /** * Let < mean "more specific" * Subtype < supertype diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt b/compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt new file mode 100644 index 00000000000..b1504a71400 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt @@ -0,0 +1,25 @@ +//KT-3772 Invoke and overload resolution ambiguity +package bar + +open class A { + public fun invoke(f: A.() -> Unit) {} +} + +class B { + public fun invoke(f: B.() -> Unit) {} +} + +open class C +val C.attr = A() + +open class D: C() +val D.attr = B() + + +fun main(args: Array) { + val b = D() + b.attr {} // overload resolution ambiguity + + val d = b.attr + d {} // no error +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index b44c8e6df8b..530f0bbe8a7 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -4582,6 +4582,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/resolve/invoke/invokeAsMemberExtensionToExplicitReceiver.kt"); } + @TestMetadata("kt3772.kt") + public void testKt3772() throws Exception { + doTest("compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt"); + } + } public static Test innerSuite() {