diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/Concat.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/Concat.kt index 182c6c5cd02..586083826fb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/Concat.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/Concat.kt @@ -17,18 +17,17 @@ package org.jetbrains.kotlin.codegen.intrinsics import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.AsmUtil.genInvokeAppendMethod import org.jetbrains.kotlin.codegen.AsmUtil.genStringBuilderConstructor -import org.jetbrains.kotlin.codegen.Callable -import org.jetbrains.kotlin.codegen.CallableMethod -import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtExpression 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.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter @@ -41,11 +40,11 @@ public class Concat : IntrinsicMethod() { arguments: List, receiver: StackValue ): Type { - if (element is KtBinaryExpression && element.getOperationReference().getReferencedNameElementType() == KtTokens.PLUS) { + if (element is KtBinaryExpression && element.operationReference.getReferencedNameElementType() == KtTokens.PLUS) { // LHS + RHS genStringBuilderConstructor(v) - codegen.invokeAppend(element.getLeft()) - codegen.invokeAppend(element.getRight()) + codegen.invokeAppend(element.left) + codegen.invokeAppend(element.right) } else { // LHS?.plus(RHS) @@ -60,7 +59,6 @@ public class Concat : IntrinsicMethod() { return JAVA_STRING_TYPE } - override fun toCallable(method: CallableMethod): Callable = object : IntrinsicCallable(method) { override fun invokeMethodWithArguments( @@ -68,16 +66,37 @@ public class Concat : IntrinsicMethod() { receiver: StackValue, codegen: ExpressionCodegen ): StackValue { + if (resolvedCall.call.callElement.parent is KtCallableReferenceExpression) { + // NB we come here only in case of inlined callable reference to String::plus. + // This will map arguments properly, invoking callbacks defined in Callable. + return super.invokeMethodWithArguments(resolvedCall, receiver, codegen) + } return StackValue.operation(returnType) { - val arguments = resolvedCall.getCall().getValueArguments().map { it.getArgumentExpression()!! } + val arguments = resolvedCall.call.valueArguments.map { it.getArgumentExpression()!! } val actualType = generateImpl( codegen, it, returnType, - resolvedCall.getCall().getCallElement(), + resolvedCall.call.callElement, arguments, StackValue.receiver(resolvedCall, receiver, codegen, this) ) StackValue.coerce(actualType, returnType, it) } } + + override fun afterReceiverGeneration(v: InstructionAdapter) { + v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder") + v.dupX1() + v.swap() + v.invokespecial("java/lang/StringBuilder", "", "(Ljava/lang/String;)V", false) + } + + override fun invokeIntrinsic(v: InstructionAdapter) { + // String::plus has type String.(Any?) -> String, thus we have no argument type information + // in case of callable reference passed to a generic function, e.g.: + // charArrayOf('O', 'K').fold("", String::plus) + // TODO Make String::plus generic, and invoke proper StringBuilder#append. + AsmUtil.genInvokeAppendMethod(v, AsmTypes.OBJECT_TYPE) + v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false) + } } -} \ No newline at end of file +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicMethod.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicMethod.java index ad37de4e419..59b70780233 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicMethod.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicMethod.java @@ -37,17 +37,17 @@ public abstract class IntrinsicMethod { } @NotNull - public Callable toCallable(@NotNull CallableMethod method, boolean isSuper, @NotNull ResolvedCall resolvedCall) { + protected Callable toCallable(@NotNull CallableMethod method, boolean isSuper, @NotNull ResolvedCall resolvedCall) { return toCallable(method, isSuper); } @NotNull - public Callable toCallable(@NotNull CallableMethod method, boolean isSuperCall) { + protected Callable toCallable(@NotNull CallableMethod method, boolean isSuperCall) { return toCallable(method); } @NotNull - public Callable toCallable(@NotNull CallableMethod method) { + protected Callable toCallable(@NotNull CallableMethod method) { throw new UnsupportedOperationException("Not implemented"); } diff --git a/compiler/testData/codegen/boxWithStdlib/intrinsics/kt10131.kt b/compiler/testData/codegen/boxWithStdlib/intrinsics/kt10131.kt new file mode 100644 index 00000000000..8dfd1db030f --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/intrinsics/kt10131.kt @@ -0,0 +1,2 @@ +fun box(): String = + listOf('O', 'K').fold("", String::plus) \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/intrinsics/kt10131a.kt b/compiler/testData/codegen/boxWithStdlib/intrinsics/kt10131a.kt new file mode 100644 index 00000000000..240390106d2 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/intrinsics/kt10131a.kt @@ -0,0 +1,2 @@ +fun box(): String = + charArrayOf('O', 'K').fold("", String::plus) \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 712aaef1913..256b83e846d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -1996,6 +1996,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("kt10131.kt") + public void testKt10131() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/intrinsics/kt10131.kt"); + doTestWithStdlib(fileName); + } + + @TestMetadata("kt10131a.kt") + public void testKt10131a() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/intrinsics/kt10131a.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("kt5937.kt") public void testKt5937() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/intrinsics/kt5937.kt");