From bd88b0941d13b5718e3324a8e033fdc5f6bde100 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 9 Aug 2016 19:54:04 +0300 Subject: [PATCH] Fix incorrect unsupported error on synthetic extension call on LHS of :: #KT-13271 Fixed --- ...portedSyntheticCallableReferenceChecker.kt | 8 ++----- .../kotlin/resolve/calls/CallCompleter.kt | 8 ++----- .../kotlin/resolve/calls/util/callUtil.kt | 6 ++++++ .../bound/syntheticExtensionOnLHS.kt | 21 +++++++++++++++++++ .../bound/syntheticExtensionOnLHS.kt | 13 ++++++++++++ .../bound/syntheticExtensionOnLHS.txt | 11 ++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++++ 8 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt create mode 100644 compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.kt create mode 100644 compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.txt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/UnsupportedSyntheticCallableReferenceChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/UnsupportedSyntheticCallableReferenceChecker.kt index a2ae3d5488b..1f24cde9a6a 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/UnsupportedSyntheticCallableReferenceChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/UnsupportedSyntheticCallableReferenceChecker.kt @@ -18,8 +18,7 @@ package org.jetbrains.kotlin.resolve.jvm.checkers import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED -import org.jetbrains.kotlin.psi.KtCallableReferenceExpression -import org.jetbrains.kotlin.psi.KtNameReferenceExpression +import org.jetbrains.kotlin.resolve.calls.callUtil.isCallableReference import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall @@ -27,11 +26,8 @@ import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor class UnsupportedSyntheticCallableReferenceChecker : CallChecker { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { - val expression = resolvedCall.call.callElement - if (expression !is KtNameReferenceExpression || expression.parent !is KtCallableReferenceExpression) return - // TODO: support references to synthetic Java extension properties (KT-8575) - if (resolvedCall.resultingDescriptor is SyntheticJavaPropertyDescriptor) { + if (resolvedCall.call.isCallableReference() && resolvedCall.resultingDescriptor is SyntheticJavaPropertyDescriptor) { context.trace.report(UNSUPPORTED.on(reportOn, "reference to the synthetic extension property for a Java get/set method")) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt index 428ca4c6b2e..e1ec7198b26 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.BindingContext.CONSTRAINT_SYSTEM_COMPLETER import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable +import org.jetbrains.kotlin.resolve.calls.callUtil.isCallableReference import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext @@ -175,7 +176,7 @@ class CallCompleter( val returnType = candidateDescriptor.returnType val expectedReturnType = - if (isResolvingCallableReference(call)) { + if (call.isCallableReference()) { // TODO: compute generic type argument for R in the kotlin.Function supertype (KT-12963) // TODO: also add constraints for parameter types (KT-12964) if (!TypeUtils.noExpectedType(expectedType) && expectedType.isFunctionType) getReturnTypeFromFunctionType(expectedType) @@ -241,11 +242,6 @@ class CallCompleter( setResultingSubstitutor(system.resultingSubstitutor) } - private fun isResolvingCallableReference(call: Call): Boolean { - val callElement = call.callElement - return (callElement.parent as? KtCallableReferenceExpression)?.callableReference == callElement - } - private fun MutableResolvedCall.updateResolutionStatusFromConstraintSystem( context: BasicCallResolutionContext, tracing: TracingStrategy diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt index f32933997b2..2432fd5d459 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt @@ -229,6 +229,12 @@ fun Call.isSafeCall(): Boolean { fun Call.isExplicitSafeCall(): Boolean = callOperationNode?.elementType == KtTokens.SAFE_ACCESS +fun Call.isCallableReference(): Boolean { + val callElement = callElement + return callElement is KtNameReferenceExpression && + (callElement.parent as? KtCallableReferenceExpression)?.callableReference == callElement +} + fun Call.createLookupLocation(): KotlinLookupLocation { val calleeExpression = calleeExpression val element = diff --git a/compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt b/compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt new file mode 100644 index 00000000000..d13956b6841 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt @@ -0,0 +1,21 @@ +// WITH_RUNTIME +// FILE: A.java + +public class A { + private final String field; + + public A(String field) { + this.field = field; + } + + public CharSequence getFoo() { return field; } +} + +// FILE: test.kt + +fun box(): String { + with (A("OK")) { + val k = foo::toString + return k() + } +} diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.kt b/compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.kt new file mode 100644 index 00000000000..43b869004af --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.kt @@ -0,0 +1,13 @@ +// FILE: A.java + +class A { + public CharSequence getFoo() { return null; } +} + +// FILE: test.kt + +fun test() { + with (A()) { + foo::toString + } +} diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.txt b/compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.txt new file mode 100644 index 00000000000..da356a5e94b --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.txt @@ -0,0 +1,11 @@ +package + +public fun test(): kotlin.Unit + +public/*package*/ open class A { + public/*package*/ constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun getFoo(): kotlin.CharSequence! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 81c0723a8c5..6e151f771fa 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -1811,6 +1811,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("syntheticExtensionOnLHS.kt") + public void testSyntheticExtensionOnLHS() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/syntheticExtensionOnLHS.kt"); + doTest(fileName); + } + @TestMetadata("valueOfTypeParameterType.kt") public void testValueOfTypeParameterType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/valueOfTypeParameterType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index ebb671bfbbc..fe1107abe35 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -1500,6 +1500,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("syntheticExtensionOnLHS.kt") + public void testSyntheticExtensionOnLHS() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/bound/syntheticExtensionOnLHS.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/codegen/box/callableReference/bound/inline") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)