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 b85fd26ebbd..fb2ce4c4b0c 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 @@ -26292,6 +26292,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("anyAnnotationDisablesIndyLambdaGeneration.kt") + public void testAnyAnnotationDisablesIndyLambdaGeneration() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/lambdas/anyAnnotationDisablesIndyLambdaGeneration.kt"); + } + @Test @TestMetadata("bigArityExtLambda.kt") public void testBigArityExtLambda() throws Exception { @@ -26346,6 +26352,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/lambdas/kt52875.kt"); } + @Test + @TestMetadata("lambdaMetadataFactoryIsNotUsed.kt") + public void testLambdaMetadataFactoryIsNotUsed() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetadataFactoryIsNotUsed.kt"); + } + + @Test + @TestMetadata("lambdaMetafactoryIsUsed.kt") + public void testLambdaMetafactoryIsUsed() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetafactoryIsUsed.kt"); + } + @Test @TestMetadata("lambdaSerializable.kt") public void testLambdaSerializable() throws Exception { 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 37e1f1f10cd..9b6ad402c2e 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 @@ -326,7 +326,7 @@ internal class LambdaMetafactoryArgumentsBuilder( return null adaptFakeInstanceMethodSignature(fakeInstanceMethod, signatureAdaptationConstraints) - if (implFun.origin in adaptableFunctionOrigins) { + if (implFun.isAdaptable()) { adaptLambdaSignature(implFun as IrSimpleFunction, fakeInstanceMethod, signatureAdaptationConstraints) } else if ( !checkMethodSignatureCompliance(implFun, fakeInstanceMethod, signatureAdaptationConstraints, reference) @@ -386,19 +386,22 @@ internal class LambdaMetafactoryArgumentsBuilder( TypeAdaptationConstraint.CONFLICT -> false } - private val adaptableFunctionOrigins = setOf( - IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA, - JvmLoweredDeclarationOrigin.PROXY_FUN_FOR_METAFACTORY, - JvmLoweredDeclarationOrigin.SYNTHETIC_PROXY_FUN_FOR_METAFACTORY - ) + private fun IrFunction.isAdaptable() = + when (origin) { + IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA, + JvmLoweredDeclarationOrigin.PROXY_FUN_FOR_METAFACTORY, + JvmLoweredDeclarationOrigin.SYNTHETIC_PROXY_FUN_FOR_METAFACTORY -> true + IrDeclarationOrigin.LOCAL_FUNCTION -> isAnonymousFunction + else -> false + } private fun adaptLambdaSignature( implFun: IrSimpleFunction, fakeInstanceMethod: IrSimpleFunction, constraints: SignatureAdaptationConstraints ) { - if (implFun.origin !in adaptableFunctionOrigins) { - throw AssertionError("Function origin should be one of ${adaptableFunctionOrigins}: ${implFun.dump()}") + if (!implFun.isAdaptable()) { + throw AssertionError("Function origin should be adaptable: ${implFun.dump()}") } val implParameters = collectValueParameters(implFun) diff --git a/compiler/testData/codegen/box/invokedynamic/lambdas/anyAnnotationDisablesIndyLambdaGeneration.kt b/compiler/testData/codegen/box/invokedynamic/lambdas/anyAnnotationDisablesIndyLambdaGeneration.kt new file mode 100644 index 00000000000..8d1bb096e03 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/lambdas/anyAnnotationDisablesIndyLambdaGeneration.kt @@ -0,0 +1,22 @@ +// LAMBDAS: INDY +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// WITH_STDLIB + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 0 java/lang/invoke/LambdaMetafactory + +import kotlin.jvm.internal.Lambda + +@Target(AnnotationTarget.EXPRESSION) +@Retention(AnnotationRetention.SOURCE) +public annotation class SomeAnnotation + +fun box(): String { + assert((@SomeAnnotation {}) is Lambda<*>) + assert((@SomeAnnotation fun () {}) is Lambda<*>) + assert((@SomeAnnotation fun Any.() {}) is Lambda<*>) + + return "OK" +} diff --git a/compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetadataFactoryIsNotUsed.kt b/compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetadataFactoryIsNotUsed.kt new file mode 100644 index 00000000000..9f8cda57290 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetadataFactoryIsNotUsed.kt @@ -0,0 +1,31 @@ +// LAMBDAS: INDY +// TARGET_BACKEND: JVM_IR +// JVM_TARGET: 1.8 +// WITH_STDLIB + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 0 java/lang/invoke/LambdaMetafactory + + +fun box(): String { + suspend {} + + fun (a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any, w: Any) = "one too many" + + fun Any.(a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any) = "one too many" + + { a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any, w: Any -> "one too many" } + + fun local(a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any, w: Any) = "one too many" + { a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any, w: Any -> + local(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetafactoryIsUsed.kt b/compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetafactoryIsUsed.kt new file mode 100644 index 00000000000..e045f3be92f --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetafactoryIsUsed.kt @@ -0,0 +1,47 @@ +// LAMBDAS: INDY +// TARGET_BACKEND: JVM_IR +// JVM_TARGET: 1.8 +// WITH_STDLIB + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 14 java/lang/invoke/LambdaMetafactory + + +fun box(): String { + var captureMe = 0 + + fun () {} // 1 + fun (a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any) = "just enough" // 2 + fun () = ++captureMe // 3 + fun (vararg x: Int) = x // 4 + + fun Any.() {} // 5 + fun Any.(a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any) = "just enough" // 6 + fun () = ++captureMe // 7 + fun Any.(vararg x: Int) = x // 8 + + + {} // 9 + { a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any -> "just enough" } // 10 + { ++captureMe } // 11 + + + fun local1() {} + { local1() } // 12 + + fun local2(a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any) = "just enough" + { a: Any, b: Any, c: Any, d: Any, e: Any, f: Any, g: Any, h: Any, i: Any, j: Any, k: Any, l: Any, m: Any, n: Any, o: Any, + p: Any, q: Any, r: Any, s: Any, t: Any, u: Any, v: Any -> + local2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) + } // 13 + + fun local3() = ++captureMe + { local3() } // 14 + + return "OK" +} \ No newline at end of file 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 b130c64aace..92ba364af5f 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 @@ -25716,6 +25716,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Test + @TestMetadata("anyAnnotationDisablesIndyLambdaGeneration.kt") + public void testAnyAnnotationDisablesIndyLambdaGeneration() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/lambdas/anyAnnotationDisablesIndyLambdaGeneration.kt"); + } + @Test @TestMetadata("bigArityExtLambda.kt") public void testBigArityExtLambda() 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 08e86867459..34a503cc722 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 @@ -26292,6 +26292,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("anyAnnotationDisablesIndyLambdaGeneration.kt") + public void testAnyAnnotationDisablesIndyLambdaGeneration() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/lambdas/anyAnnotationDisablesIndyLambdaGeneration.kt"); + } + @Test @TestMetadata("bigArityExtLambda.kt") public void testBigArityExtLambda() throws Exception { @@ -26346,6 +26352,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/lambdas/kt52875.kt"); } + @Test + @TestMetadata("lambdaMetadataFactoryIsNotUsed.kt") + public void testLambdaMetadataFactoryIsNotUsed() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetadataFactoryIsNotUsed.kt"); + } + + @Test + @TestMetadata("lambdaMetafactoryIsUsed.kt") + public void testLambdaMetafactoryIsUsed() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/lambdas/lambdaMetafactoryIsUsed.kt"); + } + @Test @TestMetadata("lambdaSerializable.kt") public void testLambdaSerializable() 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 1302b23578e..84904847f7d 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -21676,6 +21676,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @TestMetadata("anyAnnotationDisablesIndyLambdaGeneration.kt") + public void testAnyAnnotationDisablesIndyLambdaGeneration() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/lambdas/anyAnnotationDisablesIndyLambdaGeneration.kt"); + } + @TestMetadata("bigArityLambda.kt") public void testBigArityLambda() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/lambdas/bigArityLambda.kt");