From 877dfd8ff4adb21cbc174e81304da024db7c867a Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 23 Jul 2018 17:39:43 +0200 Subject: [PATCH] Fix generic signature of FunctionN type visible from Java --- .../codegen/state/KotlinTypeMapper.java | 26 ++++++++------ .../box/functions/bigArity/callFromJava.kt | 36 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ 5 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/codegen/box/functions/bigArity/callFromJava.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index 5c56c1d3b39..1ed2860a91f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -651,17 +651,21 @@ public class KotlinTypeMapper { List parameters = classDescriptor.getDeclaredTypeParameters(); List arguments = type.getArguments(); - if (classDescriptor instanceof FunctionClassDescriptor && - ((FunctionClassDescriptor) classDescriptor).getFunctionKind() == FunctionClassDescriptor.Kind.KFunction) { - // kotlin.reflect.KFunction{n} is mapped to kotlin.reflect.KFunction on JVM (see JavaToKotlinClassMap). - // So for these classes, we need to skip all type arguments except the very last one - writeGenericArguments( - signatureVisitor, - Collections.singletonList(CollectionsKt.last(arguments)), - Collections.singletonList(CollectionsKt.last(parameters)), - mode - ); - return; + if (classDescriptor instanceof FunctionClassDescriptor) { + FunctionClassDescriptor functionClass = (FunctionClassDescriptor) classDescriptor; + if (functionClass.hasBigArity() || + functionClass.getFunctionKind() == FunctionClassDescriptor.Kind.KFunction) { + // kotlin.reflect.KFunction{n} is mapped to kotlin.reflect.KFunction (for all n), and + // kotlin.Function{n} is mapped to kotlin.jvm.functions.FunctionN (for n > 22). + // So for these classes, we need to skip all type arguments except the very last one + writeGenericArguments( + signatureVisitor, + Collections.singletonList(CollectionsKt.last(arguments)), + Collections.singletonList(CollectionsKt.last(parameters)), + mode + ); + return; + } } writeGenericArguments(signatureVisitor, arguments, parameters, mode); diff --git a/compiler/testData/codegen/box/functions/bigArity/callFromJava.kt b/compiler/testData/codegen/box/functions/bigArity/callFromJava.kt new file mode 100644 index 00000000000..6849e865c86 --- /dev/null +++ b/compiler/testData/codegen/box/functions/bigArity/callFromJava.kt @@ -0,0 +1,36 @@ +// !LANGUAGE: +FunctionTypesWithBigArity +// WITH_RUNTIME +// TARGET_BACKEND: JVM +// FILE: J.java + +import kotlin.jvm.functions.FunctionN; + +public class J { + public static String test() { + return KKt.call(new FunctionN() { + @Override + public String invoke(Object... args) { + if (args.length != getArity()) throw new IllegalArgumentException("Incorrect arity: " + args.length); + + return ((A) args[5]).getMessage() + + ((A) args[28]).getMessage(); + } + + @Override + public int getArity() { + return 30; + } + }); + } +} + +// FILE: K.kt + +class A(val message: String) + +fun call(f: (A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A) -> String): String { + val a = A("XXX") + return f(a, a, a, a, a, A("O"), a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, A("K"), a) +} + +fun box(): String = J.test() diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 2fddfad7584..16255e24df2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10623,6 +10623,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/bigArity"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("callFromJava.kt") + public void testCallFromJava() throws Exception { + runTest("compiler/testData/codegen/box/functions/bigArity/callFromJava.kt"); + } + @TestMetadata("callWithIncorrectNumberOfArguments.kt") public void testCallWithIncorrectNumberOfArguments() throws Exception { runTest("compiler/testData/codegen/box/functions/bigArity/callWithIncorrectNumberOfArguments.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index ae160947452..955bd28862b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10628,6 +10628,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/bigArity"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("callFromJava.kt") + public void testCallFromJava() throws Exception { + runTest("compiler/testData/codegen/box/functions/bigArity/callFromJava.kt"); + } + @TestMetadata("callWithIncorrectNumberOfArguments.kt") public void testCallWithIncorrectNumberOfArguments() throws Exception { runTest("compiler/testData/codegen/box/functions/bigArity/callWithIncorrectNumberOfArguments.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index bd9e6ef4d40..4e5471577d4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -10623,6 +10623,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/bigArity"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); } + @TestMetadata("callFromJava.kt") + public void testCallFromJava() throws Exception { + runTest("compiler/testData/codegen/box/functions/bigArity/callFromJava.kt"); + } + @TestMetadata("callWithIncorrectNumberOfArguments.kt") public void testCallWithIncorrectNumberOfArguments() throws Exception { runTest("compiler/testData/codegen/box/functions/bigArity/callWithIncorrectNumberOfArguments.kt");