Fix callable reference resolution regression

The regression appeared after
b5a8ffaddc
when we started trying both static and member methods until
first success and when there is no successful
we were just leaving the last one (e.g. private member)

But the actual problem is that we were commiting the trace
in case of single (but incorrect) result in resolution mode of
SHAPE_FUNCTION_ARGUMENTS when we couldn't yet choose the
correct static method

Also we shouldn't choose a shape for callable reference
using only the knowledge that result is single:
it may lead to the wrong inference result
(see test with Pattern::compile)

 #KT-17597 Fixed
This commit is contained in:
Denis Zharkov
2017-04-27 14:02:56 +03:00
parent 4b6667f599
commit c970763a7f
7 changed files with 59 additions and 2 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.calls;
import kotlin.Pair;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
@@ -265,7 +266,7 @@ public class ArgumentTypeResolver {
if (overloadResolutionResults == null) return null;
if (overloadResolutionResults.isSingleResult()) {
if (isSingleAndPossibleTransformToSuccess(overloadResolutionResults)) {
ResolvedCall<?> resolvedCall =
OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency);
if (resolvedCall == null) return null;
@@ -284,6 +285,12 @@ public class ArgumentTypeResolver {
);
}
private static boolean isSingleAndPossibleTransformToSuccess(@NotNull OverloadResolutionResults<?> overloadResolutionResults) {
if (!overloadResolutionResults.isSingleResult()) return false;
ResolvedCall<?> call = CollectionsKt.singleOrNull(overloadResolutionResults.getResultingCalls());
return call != null && call.getStatus().possibleTransformToSuccess();
}
@NotNull
public KotlinTypeInfo getFunctionLiteralTypeInfo(
@NotNull KtExpression expression,
@@ -665,7 +665,7 @@ class DoubleColonExpressionResolver(
resolutionResults.isNothing -> null
else -> ResolutionResultsAndTraceCommitCallback(resolutionResults) {
checkReservedYield(reference, outerContext.trace)
if (resolutionMode != ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS || resolutionResults.isSingleResult) {
if (resolutionMode != ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS || resolutionResults.isSuccess) {
temporaryTrace.commit()
}
}
@@ -0,0 +1,16 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: A.java
public class A {
public static void foo() {}
public static void foo(String x) {}
private void foo(int y) {}
}
// FILE: main.kt
fun baz(x: (String) -> Unit) {}
fun bar() {
baz(A::foo)
}
@@ -0,0 +1,16 @@
package
public fun bar(): kotlin.Unit
public fun baz(/*0*/ x: (kotlin.String) -> kotlin.Unit): kotlin.Unit
public open class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
private open fun foo(/*0*/ y: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun foo(): kotlin.Unit
public open fun foo(/*0*/ x: kotlin.String!): kotlin.Unit
}
@@ -0,0 +1,6 @@
// SKIP_TXT
import java.util.regex.Pattern
val strs: List<String> = listOf("regex1", "regex2")
val patterns: List<Pattern> = strs.map(Pattern::compile)
@@ -60,6 +60,12 @@ public class DiagnosticsWithJava8TestGenerated extends AbstractDiagnosticsWithFu
doTest(fileName);
}
@TestMetadata("patternCompileCallableReference.kt")
public void testPatternCompileCallableReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/patternCompileCallableReference.kt");
doTest(fileName);
}
@TestMetadata("samWithConsumer.kt")
public void testSamWithConsumer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/samWithConsumer.kt");
@@ -11830,6 +11830,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("callableReferencesStaticMemberClash.kt")
public void testCallableReferencesStaticMemberClash() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/callableReferencesStaticMemberClash.kt");
doTest(fileName);
}
@TestMetadata("canDeclareIfSamAdapterIsInherited.kt")
public void testCanDeclareIfSamAdapterIsInherited() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/canDeclareIfSamAdapterIsInherited.kt");