diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 067912e8099..9caf4aafbc0 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -22498,12 +22498,42 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt"); } + @Test + @TestMetadata("genericFunRef.kt") + public void testGenericFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericFunRef.kt"); + } + @Test @TestMetadata("genericInnerConstructorRef.kt") public void testGenericInnerConstructorRef() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt"); } + @Test + @TestMetadata("highOrderFunRef.kt") + public void testHighOrderFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/highOrderFunRef.kt"); + } + + @Test + @TestMetadata("inlineFunRef.kt") + public void testInlineFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunRef.kt"); + } + + @Test + @TestMetadata("inlineFunWithReifiedTypeParameterRef.kt") + public void testInlineFunWithReifiedTypeParameterRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunWithReifiedTypeParameterRef.kt"); + } + + @Test + @TestMetadata("inlineHighOrderFunRef.kt") + public void testInlineHighOrderFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineHighOrderFunRef.kt"); + } + @Test @TestMetadata("innerConstructorRef.kt") public void testInnerConstructorRef() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt index 4cba2e084e0..d501d69381c 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt @@ -332,7 +332,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) } val proxyFun = context.irFactory.buildFun { - name = Name.identifier("\$proxy") + name = Name.identifier("${targetFun.name.asString()}__proxy") returnType = targetFun.returnType visibility = DescriptorVisibilities.LOCAL modality = Modality.FINAL @@ -395,6 +395,10 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) ) } + for (typeParameterIndex in targetFun.typeParameters.indices) { + targetCall.putTypeArgument(typeParameterIndex, reference.getTypeArgument(typeParameterIndex)) + } + val proxyFunBody = IrBlockBodyImpl(startOffset, endOffset).also { proxyFun.body = it } when { targetFun.isArrayOf() -> { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt index 15f48a800b4..da78230839e 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt @@ -132,8 +132,7 @@ internal class LambdaMetafactoryArgumentsBuilder( val implFun = reference.symbol.owner if (implFun.typeParameters.any { it.isReified }) { - // TODO support reified type parameters in proxy wrappers somehow? - abiHazard = true + functionHazard = true } // Don't generate references to intrinsic functions as invokedynamic (no such method exists at run-time). diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericFunRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericFunRef.kt new file mode 100644 index 00000000000..6d92f9039b3 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericFunRef.kt @@ -0,0 +1,18 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: genericFunRef.kt + +fun plusK(x: T) = x.toString() + "K" + +fun box() = J(::plusK).apply("O") + +// FILE: J.java +public interface J { + public String apply(String x); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/highOrderFunRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/highOrderFunRef.kt new file mode 100644 index 00000000000..12d654677ef --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/highOrderFunRef.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// WITH_RUNTIME + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: highOrderFunRef.kt + +fun applyO(fn: (String) -> String) = fn("O") + +fun box() = J(::applyO).invoke { it + "K" } + +// FILE: J.java +public interface J { + String invoke(kotlin.jvm.functions.Function1 fn); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunRef.kt new file mode 100644 index 00000000000..84e000e87ff --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunRef.kt @@ -0,0 +1,18 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: inlineFunRef.kt + +inline fun plusK(x: String) = x.toString() + "K" + +fun box() = J(::plusK).apply("O") + +// FILE: J.java +public interface J { + public String apply(String x); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunWithReifiedTypeParameterRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunWithReifiedTypeParameterRef.kt new file mode 100644 index 00000000000..78df5146e92 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunWithReifiedTypeParameterRef.kt @@ -0,0 +1,22 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// WITH_RUNTIME +// FULL_JDK + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: inlineFunWithReifiedTypeParameterRef.kt + +inline fun oPlus(x: T) = "O" + T::class.java.simpleName + +class K + +fun box() = J(::oPlus).apply(K()) + +// FILE: J.java +public interface J { + public String apply(K x); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineHighOrderFunRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineHighOrderFunRef.kt new file mode 100644 index 00000000000..bb3a2f2d862 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineHighOrderFunRef.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// WITH_RUNTIME + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: inlineHighOrderFunRef.kt + +inline fun applyO(fn: (String) -> String) = fn("O") + +fun box() = J(::applyO).invoke { it + "K" } + +// FILE: J.java +public interface J { + String invoke(kotlin.jvm.functions.Function1 fn); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayOf.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayOf.kt index dcf075e2e3c..e238986fb1d 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayOf.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayOf.kt @@ -4,7 +4,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: arrayOf.kt fun box() = diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValueOf.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValueOf.kt index 623e403be4c..67d3eabd2be 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValueOf.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValueOf.kt @@ -4,7 +4,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: enumValues.kt enum class ABC(val x: String = "") { diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt index 6b8ffc584d8..de924530c2a 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt @@ -4,7 +4,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: enumValues.kt enum class ABC(val x: String = "") { diff --git a/compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt b/compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt index d1491fcd726..e717d76ac62 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt @@ -6,7 +6,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: reifiedTypeParameter.kt diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 6f983780d64..3b4e469b5fa 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -22360,12 +22360,42 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt"); } + @Test + @TestMetadata("genericFunRef.kt") + public void testGenericFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericFunRef.kt"); + } + @Test @TestMetadata("genericInnerConstructorRef.kt") public void testGenericInnerConstructorRef() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt"); } + @Test + @TestMetadata("highOrderFunRef.kt") + public void testHighOrderFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/highOrderFunRef.kt"); + } + + @Test + @TestMetadata("inlineFunRef.kt") + public void testInlineFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunRef.kt"); + } + + @Test + @TestMetadata("inlineFunWithReifiedTypeParameterRef.kt") + public void testInlineFunWithReifiedTypeParameterRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunWithReifiedTypeParameterRef.kt"); + } + + @Test + @TestMetadata("inlineHighOrderFunRef.kt") + public void testInlineHighOrderFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineHighOrderFunRef.kt"); + } + @Test @TestMetadata("innerConstructorRef.kt") public void testInnerConstructorRef() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 10f80599d72..42412e10039 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -22498,12 +22498,42 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt"); } + @Test + @TestMetadata("genericFunRef.kt") + public void testGenericFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericFunRef.kt"); + } + @Test @TestMetadata("genericInnerConstructorRef.kt") public void testGenericInnerConstructorRef() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt"); } + @Test + @TestMetadata("highOrderFunRef.kt") + public void testHighOrderFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/highOrderFunRef.kt"); + } + + @Test + @TestMetadata("inlineFunRef.kt") + public void testInlineFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunRef.kt"); + } + + @Test + @TestMetadata("inlineFunWithReifiedTypeParameterRef.kt") + public void testInlineFunWithReifiedTypeParameterRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunWithReifiedTypeParameterRef.kt"); + } + + @Test + @TestMetadata("inlineHighOrderFunRef.kt") + public void testInlineHighOrderFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineHighOrderFunRef.kt"); + } + @Test @TestMetadata("innerConstructorRef.kt") public void testInnerConstructorRef() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 464e3d98155..d1886274a6c 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -18720,11 +18720,36 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt"); } + @TestMetadata("genericFunRef.kt") + public void testGenericFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericFunRef.kt"); + } + @TestMetadata("genericInnerConstructorRef.kt") public void testGenericInnerConstructorRef() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt"); } + @TestMetadata("highOrderFunRef.kt") + public void testHighOrderFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/highOrderFunRef.kt"); + } + + @TestMetadata("inlineFunRef.kt") + public void testInlineFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunRef.kt"); + } + + @TestMetadata("inlineFunWithReifiedTypeParameterRef.kt") + public void testInlineFunWithReifiedTypeParameterRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineFunWithReifiedTypeParameterRef.kt"); + } + + @TestMetadata("inlineHighOrderFunRef.kt") + public void testInlineHighOrderFunRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/inlineHighOrderFunRef.kt"); + } + @TestMetadata("innerConstructorRef.kt") public void testInnerConstructorRef() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt");