From 91e486d02064ab09640e46374da4cc2d5fa52ad3 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 14 Jul 2016 18:28:46 +0300 Subject: [PATCH] Fix KCallable#name intrinsic for bound references Do not skip generation of the left-hand side because it may produce side effects #KT-12995 Fixed --- .../intrinsics/KCallableNameProperty.kt | 20 ++++++++++++++----- .../bound/kCallableNameIntrinsic.kt | 10 ++++++++++ .../bytecodeListing/callableNameIntrinsic.kt | 3 +++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++++ 4 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/box/callableReference/bound/kCallableNameIntrinsic.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/KCallableNameProperty.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/KCallableNameProperty.kt index dd6b9cb1df8..65e24973a95 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/KCallableNameProperty.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/KCallableNameProperty.kt @@ -19,23 +19,33 @@ package org.jetbrains.kotlin.codegen.intrinsics import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.psi.KtCallableReferenceExpression +import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.jvm.AsmTypes +import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.kotlin.types.expressions.DoubleColonLHS import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.Type.VOID_TYPE class KCallableNameProperty : IntrinsicPropertyGetter() { override fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? { val expressionReceiver = resolvedCall!!.dispatchReceiver as? ExpressionReceiver ?: return null val expression = expressionReceiver.expression as? KtCallableReferenceExpression ?: return null + + val receiverExpression = expression.receiverExpression + val lhs = receiverExpression?.let { codegen.bindingContext.get(DOUBLE_COLON_LHS, it) } + val callableReference = expression.callableReference val descriptor = callableReference.getResolvedCall(codegen.bindingContext)?.resultingDescriptor ?: return null - val name = descriptor.name.asString() return StackValue.operation(returnType) { iv -> - iv.aconst(name) - StackValue.coerce(AsmTypes.JAVA_STRING_TYPE, returnType, iv) + // Generate the left-hand side of a bound callable reference expression + if (lhs is DoubleColonLHS.Expression) { + codegen.gen(receiverExpression, VOID_TYPE) + } + iv.aconst(descriptor.name.asString()) + StackValue.coerce(JAVA_STRING_TYPE, returnType, iv) } } -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/callableReference/bound/kCallableNameIntrinsic.kt b/compiler/testData/codegen/box/callableReference/bound/kCallableNameIntrinsic.kt new file mode 100644 index 00000000000..9f654484720 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/bound/kCallableNameIntrinsic.kt @@ -0,0 +1,10 @@ +// See KT-12995 + +fun box(): String { + var state = 0 + val name = (state++)::toString.name + if (name != "toString") return "Fail 1: $name" + if (state != 1) return "Fail 2: $state" + + return "OK" +} diff --git a/compiler/testData/codegen/bytecodeListing/callableNameIntrinsic.kt b/compiler/testData/codegen/bytecodeListing/callableNameIntrinsic.kt index f321d18358c..c607b5ba4ba 100644 --- a/compiler/testData/codegen/bytecodeListing/callableNameIntrinsic.kt +++ b/compiler/testData/codegen/bytecodeListing/callableNameIntrinsic.kt @@ -6,5 +6,8 @@ class A { val a = A::a.name val b = A::b.name val c = ::A.name + + val d = this::a.name + val e = A()::b.name } } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 5e634405820..268681f2ed8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -1476,6 +1476,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("kCallableNameIntrinsic.kt") + public void testKCallableNameIntrinsic() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/bound/kCallableNameIntrinsic.kt"); + doTest(fileName); + } + @TestMetadata("kt12738.kt") public void testKt12738() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/bound/kt12738.kt");