Fix generic signature of FunctionN type visible from Java

This commit is contained in:
Alexander Udalov
2018-07-23 17:39:43 +02:00
committed by Ilya Gorbunov
parent 348ce6733d
commit 877dfd8ff4
5 changed files with 66 additions and 11 deletions
@@ -651,17 +651,21 @@ public class KotlinTypeMapper {
List<TypeParameterDescriptor> parameters = classDescriptor.getDeclaredTypeParameters();
List<TypeProjection> arguments = type.getArguments();
if (classDescriptor instanceof FunctionClassDescriptor &&
((FunctionClassDescriptor) classDescriptor).getFunctionKind() == FunctionClassDescriptor.Kind.KFunction) {
// kotlin.reflect.KFunction{n}<P1, ... Pn, R> is mapped to kotlin.reflect.KFunction<R> 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}<P1, ..., Pn, R> is mapped to kotlin.reflect.KFunction<R> (for all n), and
// kotlin.Function{n}<P1, ..., Pn, R> is mapped to kotlin.jvm.functions.FunctionN<R> (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);
@@ -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<String>() {
@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()
@@ -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");
@@ -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");
@@ -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");