diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index bc618c157d5..d80cc6f78e3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -748,9 +748,16 @@ class PsiInlineCodegen( val receiverValue = getBoundCallableReferenceReceiver(argumentExpression) if (receiverValue != null) { val receiver = codegen.generateReceiverValue(receiverValue, false) + val receiverKotlinType = receiver.kotlinType + val boxedReceiver = + if (receiverKotlinType != null) + receiver.type.boxReceiverForBoundReference(receiverKotlinType, state) + else + receiver.type.boxReceiverForBoundReference() + putClosureParametersOnStack( lambdaInfo, - StackValue.coercion(receiver, receiver.type.boxReceiverForBoundReference(), null) + StackValue.coercion(receiver, boxedReceiver, receiverKotlinType) ) } } else { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt index a44c87b29ef..0cc7a4737a4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding.* import org.jetbrains.kotlin.codegen.binding.MutableClosure import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor +import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* @@ -22,6 +23,7 @@ import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert import org.jetbrains.kotlin.resolve.jvm.AsmTypes +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.ClassVisitor @@ -173,7 +175,11 @@ class DefaultLambda( } } -fun Type.boxReceiverForBoundReference() = AsmUtil.boxType(this) +fun Type.boxReceiverForBoundReference() = + AsmUtil.boxType(this) + +fun Type.boxReceiverForBoundReference(kotlinType: KotlinType, state: GenerationState) = + AsmUtil.boxType(this, kotlinType, state) abstract class ExpressionLambda(protected val typeMapper: KotlinTypeMapper, isCrossInline: Boolean) : LambdaInfo(isCrossInline) { diff --git a/compiler/testData/codegen/box/inlineClasses/boundCallableReferencePassedToInlineFunction.kt b/compiler/testData/codegen/box/inlineClasses/boundCallableReferencePassedToInlineFunction.kt new file mode 100644 index 00000000000..1d61703e40f --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/boundCallableReferencePassedToInlineFunction.kt @@ -0,0 +1,65 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JVM_IR + +inline class IcInt(val i: Int) { + fun simple(): String = i.toString() +} + +inline class IcLong(val l: Long) { + fun simple(): String = l.toString() +} + +inline class IcAny(val a: Any?) { + fun simple(): String = a?.toString() ?: "null" +} + +inline class IcOverIc(val o: IcLong) { + fun simple(): String = o.toString() +} + +fun testUnboxed(i: IcInt, l: IcLong, a: IcAny, o: IcOverIc): String = + foo(i::simple) + foo(l::simple) + foo(a::simple) + foo(o::simple) + +fun testBoxed(i: IcInt?, l: IcLong?, a: IcAny?, o: IcOverIc?): String = + foo(i!!::simple) + foo(l!!::simple) + foo(a!!::simple) + foo(o!!::simple) + +fun testLocalVars(): String { + val i = IcInt(0) + val l = IcLong(1L) + val a = IcAny(2) + val o = IcOverIc(IcLong(3)) + + return foo(i::simple) + foo(l::simple) + foo(a::simple) + foo(o::simple) +} + +val ip = IcInt(1) +val lp = IcLong(2L) +val ap = IcAny(3) +val op = IcOverIc(IcLong(4)) + +fun testGlobalProperties(): String = + foo(ip::simple) + foo(lp::simple) + foo(ap::simple) + foo(op::simple) + +fun testCapturedVars(): String { + return IcInt(2).let { foo(it::simple) } + + IcLong(3).let { foo(it::simple) } + + IcAny(4).let { foo(it::simple) } + + IcOverIc(IcLong(5)).let { foo(it::simple) } +} + +inline fun foo(init: () -> String): String = init() + +fun box(): String { + val i = IcInt(3) + val l = IcLong(4) + val a = IcAny(5) + val o = IcOverIc(IcLong(6)) + + if (testUnboxed(i, l, a, o) != "345IcLong(l=6)") return "Fail 1" + if (testBoxed(i, l, a, o) != "345IcLong(l=6)") return "Fail 2" + if (testLocalVars() != "012IcLong(l=3)") return "Fail 3" + if (testGlobalProperties() != "123IcLong(l=4)") return "Fail 4" + if (testCapturedVars() != "234IcLong(l=5)") return "Fail 5" + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 21ad4313965..43fbc63565d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11665,6 +11665,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("boundCallableReferencePassedToInlineFunction.kt") + public void testBoundCallableReferencePassedToInlineFunction() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boundCallableReferencePassedToInlineFunction.kt"); + } + @TestMetadata("boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt") public void testBoxNullableValueOfInlineClassWithNonNullUnderlyingType() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 08ca5adf5a0..f02f0a1b02a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11665,6 +11665,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("boundCallableReferencePassedToInlineFunction.kt") + public void testBoundCallableReferencePassedToInlineFunction() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boundCallableReferencePassedToInlineFunction.kt"); + } + @TestMetadata("boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt") public void testBoxNullableValueOfInlineClassWithNonNullUnderlyingType() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 475553062e0..725fbc275cf 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -11670,6 +11670,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); } + @TestMetadata("boundCallableReferencePassedToInlineFunction.kt") + public void testBoundCallableReferencePassedToInlineFunction() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boundCallableReferencePassedToInlineFunction.kt"); + } + @TestMetadata("boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt") public void testBoxNullableValueOfInlineClassWithNonNullUnderlyingType() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index 52004b81b1a..9683a32368c 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -10095,6 +10095,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); } + @TestMetadata("boundCallableReferencePassedToInlineFunction.kt") + public void testBoundCallableReferencePassedToInlineFunction() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boundCallableReferencePassedToInlineFunction.kt"); + } + @TestMetadata("boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt") public void testBoxNullableValueOfInlineClassWithNonNullUnderlyingType() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 93a57fbb763..bb2209ad090 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -11140,6 +11140,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); } + @TestMetadata("boundCallableReferencePassedToInlineFunction.kt") + public void testBoundCallableReferencePassedToInlineFunction() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boundCallableReferencePassedToInlineFunction.kt"); + } + @TestMetadata("boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt") public void testBoxNullableValueOfInlineClassWithNonNullUnderlyingType() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithNonNullUnderlyingType.kt");