Support function types with >= 23 parameters
See https://github.com/Kotlin/KEEP/issues/107 #KT-13764 Fixed
This commit is contained in:
@@ -719,14 +719,24 @@ public class AsmUtil {
|
||||
KotlinType type = parameter.getType();
|
||||
if (isNullableType(type) || InlineClassesUtilsKt.isNullableUnderlyingType(type)) return;
|
||||
|
||||
int index = frameMap.getIndex(parameter);
|
||||
Type asmType = typeMapper.mapType(type);
|
||||
if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) {
|
||||
v.load(index, asmType);
|
||||
StackValue value;
|
||||
if (JvmCodegenUtil.isDeclarationOfBigArityFunctionInvoke(parameter.getContainingDeclaration())) {
|
||||
int index = getIndexOfParameterInVarargInvokeArray(parameter);
|
||||
value = StackValue.arrayElement(
|
||||
OBJECT_TYPE, null, StackValue.local(1, getArrayType(OBJECT_TYPE)), StackValue.constant(index)
|
||||
);
|
||||
}
|
||||
else {
|
||||
int index = frameMap.getIndex(parameter);
|
||||
value = StackValue.local(index, asmType);
|
||||
}
|
||||
value.put(asmType, v);
|
||||
v.visitLdcInsn(name);
|
||||
String checkMethod = "checkParameterIsNotNull";
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, checkMethod,
|
||||
"(Ljava/lang/Object;Ljava/lang/String;)V", false);
|
||||
v.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkParameterIsNotNull", "(Ljava/lang/Object;Ljava/lang/String;)V", false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,6 +766,28 @@ public class AsmUtil {
|
||||
};
|
||||
}
|
||||
|
||||
private static int getIndexOfParameterInVarargInvokeArray(@NotNull ParameterDescriptor parameter) {
|
||||
if (parameter instanceof ReceiverParameterDescriptor) return 0;
|
||||
|
||||
DeclarationDescriptor container = parameter.getContainingDeclaration();
|
||||
assert parameter instanceof ValueParameterDescriptor : "Non-extension-receiver parameter must be a value parameter: " + parameter;
|
||||
int extensionShift = ((CallableDescriptor) container).getExtensionReceiverParameter() == null ? 0 : 1;
|
||||
|
||||
return extensionShift + ((ValueParameterDescriptor) parameter).getIndex();
|
||||
}
|
||||
|
||||
// At the beginning of the vararg invoke of a function with big arity N, generates an assert that the vararg parameter has N elements
|
||||
public static void generateVarargInvokeArityAssert(InstructionAdapter v, int functionArity) {
|
||||
Label start = new Label();
|
||||
v.load(1, getArrayType(OBJECT_TYPE));
|
||||
v.arraylength();
|
||||
v.iconst(functionArity);
|
||||
v.ificmpeq(start);
|
||||
v.visitLdcInsn("Vararg argument must contain " + functionArity + " elements.");
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwIllegalArgument", "(Ljava/lang/String;)V", false);
|
||||
v.visitLabel(start);
|
||||
}
|
||||
|
||||
public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
|
||||
v.aconst(null);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.ValueArgument;
|
||||
@@ -18,12 +19,14 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.StackValue.createDefaultValue;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
|
||||
public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
private final ExpressionCodegen codegen;
|
||||
private final CallGenerator callGenerator;
|
||||
private final List<ValueParameterDescriptor> valueParameters;
|
||||
private final List<Type> valueParameterTypes;
|
||||
private final boolean isVarargInvoke;
|
||||
|
||||
public CallBasedArgumentGenerator(
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@@ -36,19 +39,23 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
this.valueParameters = valueParameters;
|
||||
this.valueParameterTypes = valueParameterTypes;
|
||||
|
||||
assert valueParameters.size() == valueParameterTypes.size() :
|
||||
"Value parameters and their types mismatch in sizes: " + valueParameters.size() + " != " + valueParameterTypes.size();
|
||||
CallableDescriptor container = valueParameters.isEmpty() ? null : valueParameters.get(0).getContainingDeclaration();
|
||||
this.isVarargInvoke = JvmCodegenUtil.isDeclarationOfBigArityFunctionInvoke(container);
|
||||
|
||||
if (!isVarargInvoke) {
|
||||
assert valueParameters.size() == valueParameterTypes.size() :
|
||||
"Value parameters and their types mismatch in sizes: " + valueParameters.size() + " != " + valueParameterTypes.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateExpression(int i, @NotNull ExpressionValueArgument argument) {
|
||||
ValueParameterDescriptor parameter = valueParameters.get(i);
|
||||
Type type = valueParameterTypes.get(i);
|
||||
ValueArgument valueArgument = argument.getValueArgument();
|
||||
assert valueArgument != null;
|
||||
KtExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
assert argumentExpression != null : valueArgument.asElement().getText();
|
||||
callGenerator.genValueAndPut(parameter, argumentExpression, type, i);
|
||||
callGenerator.genValueAndPut(parameter, argumentExpression, isVarargInvoke ? OBJECT_TYPE : valueParameterTypes.get(i), i);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
enum class ValueKind {
|
||||
@@ -46,12 +47,30 @@ interface CallGenerator {
|
||||
}
|
||||
|
||||
override fun genValueAndPut(
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
argumentExpression: KtExpression,
|
||||
parameterType: Type,
|
||||
parameterIndex: Int) {
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
argumentExpression: KtExpression,
|
||||
parameterType: Type,
|
||||
parameterIndex: Int
|
||||
) {
|
||||
val container = valueParameterDescriptor.containingDeclaration
|
||||
val isVarargInvoke = JvmCodegenUtil.isDeclarationOfBigArityFunctionInvoke(container)
|
||||
|
||||
val v = codegen.v
|
||||
if (isVarargInvoke) {
|
||||
if (parameterIndex == 0) {
|
||||
v.iconst(container.valueParameters.size)
|
||||
v.newarray(OBJECT_TYPE)
|
||||
}
|
||||
v.dup()
|
||||
v.iconst(parameterIndex)
|
||||
}
|
||||
|
||||
val value = codegen.gen(argumentExpression)
|
||||
value.put(parameterType, valueParameterDescriptor.original.type, codegen.v)
|
||||
value.put(parameterType, valueParameterDescriptor.original.type, v)
|
||||
|
||||
if (isVarargInvoke) {
|
||||
v.astore(OBJECT_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun putCapturedValueOnStack(
|
||||
|
||||
@@ -199,7 +199,8 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
typeMapper.mapAsmMethod(erasedInterfaceFunction),
|
||||
erasedInterfaceFunction.getReturnType(),
|
||||
typeMapper.mapAsmMethod(funDescriptor),
|
||||
funDescriptor.getReturnType()
|
||||
funDescriptor.getReturnType(),
|
||||
JvmCodegenUtil.isDeclarationOfBigArityFunctionInvoke(erasedInterfaceFunction)
|
||||
);
|
||||
|
||||
//TODO: rewrite cause ugly hack
|
||||
@@ -270,7 +271,8 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
@NotNull Method bridge,
|
||||
@Nullable KotlinType bridgeReturnType,
|
||||
@NotNull Method delegate,
|
||||
@Nullable KotlinType delegateReturnType
|
||||
@Nullable KotlinType delegateReturnType,
|
||||
boolean isVarargInvoke
|
||||
) {
|
||||
if (bridge.equals(delegate)) return;
|
||||
|
||||
@@ -285,9 +287,14 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
MemberCodegen.markLineNumberForDescriptor(DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);
|
||||
|
||||
iv.load(0, asmType);
|
||||
|
||||
Type[] myParameterTypes = bridge.getArgumentTypes();
|
||||
if (isVarargInvoke) {
|
||||
assert myParameterTypes.length == 1 && myParameterTypes[0].equals(AsmUtil.getArrayType(OBJECT_TYPE)) :
|
||||
"Vararg invoke must have one parameter of type [Ljava/lang/Object;: " + bridge;
|
||||
generateVarargInvokeArityAssert(iv, delegate.getArgumentTypes().length);
|
||||
}
|
||||
|
||||
iv.load(0, asmType);
|
||||
|
||||
List<ParameterDescriptor> calleeParameters = CollectionsKt.plus(
|
||||
CollectionsKt.listOfNotNull(funDescriptor.getExtensionReceiverParameter()),
|
||||
@@ -296,11 +303,20 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
|
||||
int slot = 1;
|
||||
for (int i = 0; i < calleeParameters.size(); i++) {
|
||||
Type type = myParameterTypes[i];
|
||||
ParameterDescriptor calleeParameter = calleeParameters.get(i);
|
||||
KotlinType parameterType = calleeParameter.getType();
|
||||
StackValue.local(slot, type, parameterType).put(typeMapper.mapType(calleeParameter), parameterType, iv);
|
||||
slot += type.getSize();
|
||||
StackValue value;
|
||||
if (isVarargInvoke) {
|
||||
value = StackValue.arrayElement(
|
||||
OBJECT_TYPE, null, StackValue.local(1, myParameterTypes[0], parameterType), StackValue.constant(i)
|
||||
);
|
||||
}
|
||||
else {
|
||||
Type type = myParameterTypes[i];
|
||||
value = StackValue.local(slot, type, parameterType);
|
||||
slot += type.getSize();
|
||||
}
|
||||
value.put(typeMapper.mapType(calleeParameter), parameterType, iv);
|
||||
}
|
||||
|
||||
iv.invokevirtual(asmType.getInternalName(), delegate.getName(), delegate.getDescriptor(), false);
|
||||
|
||||
@@ -1417,17 +1417,29 @@ public class FunctionCodegen {
|
||||
if (!state.getClassBuilderMode().generateBodies) return;
|
||||
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
Type[] argTypes = bridge.getArgumentTypes();
|
||||
Type[] originalArgTypes = delegateTo.getArgumentTypes();
|
||||
|
||||
List<ParameterDescriptor> allKotlinParameters = new ArrayList<>(argTypes.length);
|
||||
List<ParameterDescriptor> allKotlinParameters = new ArrayList<>(originalArgTypes.length);
|
||||
if (descriptor.getExtensionReceiverParameter() != null) allKotlinParameters.add(descriptor.getExtensionReceiverParameter());
|
||||
allKotlinParameters.addAll(descriptor.getValueParameters());
|
||||
|
||||
boolean safeToUseKotlinTypes = allKotlinParameters.size() == argTypes.length;
|
||||
boolean safeToUseKotlinTypes = allKotlinParameters.size() == originalArgTypes.length;
|
||||
|
||||
boolean isVarargInvoke = JvmCodegenUtil.isOverrideOfBigArityFunctionInvoke(descriptor);
|
||||
if (isVarargInvoke) {
|
||||
assert argTypes.length == 1 && argTypes[0].equals(AsmUtil.getArrayType(OBJECT_TYPE)) :
|
||||
"Vararg invoke must have one parameter of type [Ljava/lang/Object;: " + bridge;
|
||||
AsmUtil.generateVarargInvokeArityAssert(iv, originalArgTypes.length);
|
||||
}
|
||||
else {
|
||||
assert argTypes.length == originalArgTypes.length :
|
||||
"Number of parameters of the bridge and delegate must be the same.\n" +
|
||||
"Descriptor: " + descriptor + "\nBridge: " + bridge + "\nDelegate: " + delegateTo;
|
||||
}
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);
|
||||
|
||||
if (delegateTo.getArgumentTypes().length > 0 && isSpecialBridge) {
|
||||
@@ -1435,11 +1447,18 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
for (int i = 0, reg = 1; i < originalArgTypes.length; i++) {
|
||||
KotlinType kotlinType = safeToUseKotlinTypes ? allKotlinParameters.get(i).getType() : null;
|
||||
StackValue.local(reg, argTypes[i], kotlinType).put(originalArgTypes[i], kotlinType, iv);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argTypes[i].getSize();
|
||||
StackValue value;
|
||||
if (isVarargInvoke) {
|
||||
value = StackValue.arrayElement(OBJECT_TYPE, null, StackValue.local(1, argTypes[0]), StackValue.constant(i));
|
||||
}
|
||||
else {
|
||||
value = StackValue.local(reg, argTypes[i], kotlinType);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argTypes[i].getSize();
|
||||
}
|
||||
value.put(originalArgTypes[i], kotlinType, iv);
|
||||
}
|
||||
|
||||
if (isStubDeclarationWithDelegationToSuper) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import kotlin.collections.CollectionsKt;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor;
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.FacadePartWithSourceFile;
|
||||
@@ -38,6 +39,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -348,4 +350,17 @@ public class JvmCodegenUtil {
|
||||
kind != OwnerKind.DEFAULT_IMPLS &&
|
||||
!Boolean.FALSE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor));
|
||||
}
|
||||
|
||||
public static boolean isDeclarationOfBigArityFunctionInvoke(@Nullable DeclarationDescriptor descriptor) {
|
||||
return descriptor instanceof FunctionInvokeDescriptor && ((FunctionInvokeDescriptor) descriptor).hasBigArity();
|
||||
}
|
||||
|
||||
public static boolean isOverrideOfBigArityFunctionInvoke(@Nullable DeclarationDescriptor descriptor) {
|
||||
return descriptor instanceof FunctionDescriptor &&
|
||||
descriptor.getName().equals(OperatorNameConventions.INVOKE) &&
|
||||
CollectionsKt.any(
|
||||
DescriptorUtils.getAllOverriddenDeclarations((FunctionDescriptor) descriptor),
|
||||
JvmCodegenUtil::isDeclarationOfBigArityFunctionInvoke
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
|
||||
|
||||
abstract class AbstractCoroutineCodegen(
|
||||
outerExpressionCodegen: ExpressionCodegen,
|
||||
element: KtElement,
|
||||
@@ -228,7 +227,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
val bridgeParameters = (1 until delegate.argumentTypes.size).map { AsmTypes.OBJECT_TYPE } + delegate.argumentTypes.last()
|
||||
val bridge = Method(delegate.name, delegate.returnType, bridgeParameters.toTypedArray())
|
||||
|
||||
generateBridge(bridge, createCoroutineDescriptor.returnType, delegate, createCoroutineDescriptor.returnType)
|
||||
generateBridge(bridge, createCoroutineDescriptor.returnType, delegate, createCoroutineDescriptor.returnType, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
@@ -1172,7 +1173,16 @@ public class KotlinTypeMapper {
|
||||
skipGenericSignature);
|
||||
}
|
||||
|
||||
return mapSignatureWithCustomParameters(f, kind, f.getValueParameters(), skipGenericSignature, hasSpecialBridge);
|
||||
if (isDeclarationOfBigArityFunctionInvoke(f)) {
|
||||
KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(f);
|
||||
KotlinType arrayOfNullableAny = builtIns.getArrayType(Variance.INVARIANT, builtIns.getNullableAnyType());
|
||||
return mapSignatureWithCustomParameters(f, kind, Stream.of(arrayOfNullableAny), false, false);
|
||||
}
|
||||
|
||||
return mapSignatureWithCustomParameters(
|
||||
f, kind, f.getValueParameters().stream().map(ValueParameterDescriptor::getType),
|
||||
skipGenericSignature, hasSpecialBridge
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1182,14 +1192,17 @@ public class KotlinTypeMapper {
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
boolean skipGenericSignature
|
||||
) {
|
||||
return mapSignatureWithCustomParameters(f, kind, valueParameters, skipGenericSignature, false);
|
||||
return mapSignatureWithCustomParameters(
|
||||
f, kind, valueParameters.stream().map(ValueParameterDescriptor::getType),
|
||||
skipGenericSignature, false
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JvmMethodGenericSignature mapSignatureWithCustomParameters(
|
||||
@NotNull FunctionDescriptor f,
|
||||
@NotNull OwnerKind kind,
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
@NotNull Stream<KotlinType> valueParameterTypes,
|
||||
boolean skipGenericSignature,
|
||||
boolean hasSpecialBridge
|
||||
) {
|
||||
@@ -1203,9 +1216,7 @@ public class KotlinTypeMapper {
|
||||
sw.writeParametersStart();
|
||||
writeAdditionalConstructorParameters((ClassConstructorDescriptor) f, sw);
|
||||
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
writeParameter(sw, parameter.getType(), f);
|
||||
}
|
||||
valueParameterTypes.forEach(type -> writeParameter(sw, type, f));
|
||||
|
||||
if (f instanceof AccessorForConstructorDescriptor) {
|
||||
writeParameter(sw, JvmMethodParameterKind.CONSTRUCTOR_MARKER, DEFAULT_CONSTRUCTOR_MARKER);
|
||||
@@ -1242,14 +1253,10 @@ public class KotlinTypeMapper {
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType(), f);
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
valueParameterTypes.forEach(type -> {
|
||||
boolean forceBoxing = MethodSignatureMappingKt.forceSingleValueParameterBoxing(f);
|
||||
writeParameter(
|
||||
sw,
|
||||
forceBoxing ? TypeUtils.makeNullable(parameter.getType()) : parameter.getType(),
|
||||
f
|
||||
);
|
||||
}
|
||||
writeParameter(sw, forceBoxing ? TypeUtils.makeNullable(type) : type, f);
|
||||
});
|
||||
|
||||
sw.writeReturnType();
|
||||
mapReturnType(f, sw);
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// WITH_RUNTIME
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: J.java
|
||||
|
||||
// import kotlin.jvm.functions.Arity;
|
||||
import kotlin.jvm.functions.FunctionN;
|
||||
import kotlin.Unit;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class J {
|
||||
// TODO: uncomment arity as soon as Arity is introduced
|
||||
public static void test(/* @Arity(30) */ FunctionN<Unit> f) {
|
||||
Object o = new Object();
|
||||
for (int i = 0; i < 42; i++) {
|
||||
if (i == 30) continue;
|
||||
|
||||
Object[] args = new Object[i];
|
||||
Arrays.fill(args, o);
|
||||
try {
|
||||
f.invoke(args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// OK
|
||||
|
||||
if (!e.getMessage().contains("30")) {
|
||||
throw new AssertionError("Exception must specify the expected number of arguments: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
continue;
|
||||
} catch (Throwable e) {
|
||||
throw new AssertionError(
|
||||
"Incorrect exception (IllegalArgumentException expected): " + e.getClass().getName() + ", i = " + i, e
|
||||
);
|
||||
}
|
||||
throw new AssertionError("IllegalArgumentException expected, but nothing was thrown, i = " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: K.kt
|
||||
|
||||
fun foo(
|
||||
p00: Any?, p01: Any?, p02: Any?, p03: Any?, p04: Any?, p05: Any?, p06: Any?, p07: Any?, p08: Any?, p09: Any?,
|
||||
p10: Any?, p11: Any?, p12: Any?, p13: Any?, p14: Any?, p15: Any?, p16: Any?, p17: Any?, p18: Any?, p19: Any?,
|
||||
p20: Any?, p21: Any?, p22: Any?, p23: Any?, p24: Any?, p25: Any?, p26: Any?, p27: Any?, p28: Any?, p29: Any?
|
||||
) {}
|
||||
|
||||
class Fun : (Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?) -> Unit {
|
||||
override fun invoke(
|
||||
p00: Any?, p01: Any?, p02: Any?, p03: Any?, p04: Any?, p05: Any?, p06: Any?, p07: Any?, p08: Any?, p09: Any?,
|
||||
p10: Any?, p11: Any?, p12: Any?, p13: Any?, p14: Any?, p15: Any?, p16: Any?, p17: Any?, p18: Any?, p19: Any?,
|
||||
p20: Any?, p21: Any?, p22: Any?, p23: Any?, p24: Any?, p25: Any?, p26: Any?, p27: Any?, p28: Any?, p29: Any?
|
||||
) {}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val lambda: Function30<
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
Unit> = { _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ -> }
|
||||
J.test(lambda as kotlin.jvm.functions.FunctionN<Unit>)
|
||||
J.test(::foo as kotlin.jvm.functions.FunctionN<Unit>)
|
||||
J.test(Fun() as kotlin.jvm.functions.FunctionN<Unit>)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
class A(val value: Int) {
|
||||
// for (i in 1..254) { print("p${"%03d".format(i)}: A, "); if (i % 10 == 0) println() }; println()
|
||||
|
||||
fun lmao(
|
||||
p001: A, p002: A, p003: A, p004: A, p005: A, p006: A, p007: A, p008: A, p009: A, p010: A,
|
||||
p011: A, p012: A, p013: A, p014: A, p015: A, p016: A, p017: A, p018: A, p019: A, p020: A,
|
||||
p021: A, p022: A, p023: A, p024: A, p025: A, p026: A, p027: A, p028: A, p029: A, p030: A,
|
||||
p031: A, p032: A, p033: A, p034: A, p035: A, p036: A, p037: A, p038: A, p039: A, p040: A,
|
||||
p041: A, p042: A, p043: A, p044: A, p045: A, p046: A, p047: A, p048: A, p049: A, p050: A,
|
||||
p051: A, p052: A, p053: A, p054: A, p055: A, p056: A, p057: A, p058: A, p059: A, p060: A,
|
||||
p061: A, p062: A, p063: A, p064: A, p065: A, p066: A, p067: A, p068: A, p069: A, p070: A,
|
||||
p071: A, p072: A, p073: A, p074: A, p075: A, p076: A, p077: A, p078: A, p079: A, p080: A,
|
||||
p081: A, p082: A, p083: A, p084: A, p085: A, p086: A, p087: A, p088: A, p089: A, p090: A,
|
||||
p091: A, p092: A, p093: A, p094: A, p095: A, p096: A, p097: A, p098: A, p099: A, p100: A,
|
||||
p101: A, p102: A, p103: A, p104: A, p105: A, p106: A, p107: A, p108: A, p109: A, p110: A,
|
||||
p111: A, p112: A, p113: A, p114: A, p115: A, p116: A, p117: A, p118: A, p119: A, p120: A,
|
||||
p121: A, p122: A, p123: A, p124: A, p125: A, p126: A, p127: A, p128: A, p129: A, p130: A,
|
||||
p131: A, p132: A, p133: A, p134: A, p135: A, p136: A, p137: A, p138: A, p139: A, p140: A,
|
||||
p141: A, p142: A, p143: A, p144: A, p145: A, p146: A, p147: A, p148: A, p149: A, p150: A,
|
||||
p151: A, p152: A, p153: A, p154: A, p155: A, p156: A, p157: A, p158: A, p159: A, p160: A,
|
||||
p161: A, p162: A, p163: A, p164: A, p165: A, p166: A, p167: A, p168: A, p169: A, p170: A,
|
||||
p171: A, p172: A, p173: A, p174: A, p175: A, p176: A, p177: A, p178: A, p179: A, p180: A,
|
||||
p181: A, p182: A, p183: A, p184: A, p185: A, p186: A, p187: A, p188: A, p189: A, p190: A,
|
||||
p191: A, p192: A, p193: A, p194: A, p195: A, p196: A, p197: A, p198: A, p199: A, p200: A,
|
||||
p201: A, p202: A, p203: A, p204: A, p205: A, p206: A, p207: A, p208: A, p209: A, p210: A,
|
||||
p211: A, p212: A, p213: A, p214: A, p215: A, p216: A, p217: A, p218: A, p219: A, p220: A,
|
||||
p221: A, p222: A, p223: A, p224: A, p225: A, p226: A, p227: A, p228: A, p229: A, p230: A,
|
||||
p231: A, p232: A, p233: A, p234: A, p235: A, p236: A, p237: A, p238: A, p239: A, p240: A,
|
||||
p241: A, p242: A, p243: A, p244: A, p245: A, p246: A, p247: A, p248: A, p249: A, p250: A,
|
||||
p251: A, p252: A, p253: A, p254: A
|
||||
) {
|
||||
check(this, 0)
|
||||
|
||||
// for (i in 1..254) { print("check(p${"%03d".format(i)}, $i)"); if (i % 6 == 0) println() else print("; ") }; println()
|
||||
|
||||
check(p001, 1); check(p002, 2); check(p003, 3); check(p004, 4); check(p005, 5); check(p006, 6)
|
||||
check(p007, 7); check(p008, 8); check(p009, 9); check(p010, 10); check(p011, 11); check(p012, 12)
|
||||
check(p013, 13); check(p014, 14); check(p015, 15); check(p016, 16); check(p017, 17); check(p018, 18)
|
||||
check(p019, 19); check(p020, 20); check(p021, 21); check(p022, 22); check(p023, 23); check(p024, 24)
|
||||
check(p025, 25); check(p026, 26); check(p027, 27); check(p028, 28); check(p029, 29); check(p030, 30)
|
||||
check(p031, 31); check(p032, 32); check(p033, 33); check(p034, 34); check(p035, 35); check(p036, 36)
|
||||
check(p037, 37); check(p038, 38); check(p039, 39); check(p040, 40); check(p041, 41); check(p042, 42)
|
||||
check(p043, 43); check(p044, 44); check(p045, 45); check(p046, 46); check(p047, 47); check(p048, 48)
|
||||
check(p049, 49); check(p050, 50); check(p051, 51); check(p052, 52); check(p053, 53); check(p054, 54)
|
||||
check(p055, 55); check(p056, 56); check(p057, 57); check(p058, 58); check(p059, 59); check(p060, 60)
|
||||
check(p061, 61); check(p062, 62); check(p063, 63); check(p064, 64); check(p065, 65); check(p066, 66)
|
||||
check(p067, 67); check(p068, 68); check(p069, 69); check(p070, 70); check(p071, 71); check(p072, 72)
|
||||
check(p073, 73); check(p074, 74); check(p075, 75); check(p076, 76); check(p077, 77); check(p078, 78)
|
||||
check(p079, 79); check(p080, 80); check(p081, 81); check(p082, 82); check(p083, 83); check(p084, 84)
|
||||
check(p085, 85); check(p086, 86); check(p087, 87); check(p088, 88); check(p089, 89); check(p090, 90)
|
||||
check(p091, 91); check(p092, 92); check(p093, 93); check(p094, 94); check(p095, 95); check(p096, 96)
|
||||
check(p097, 97); check(p098, 98); check(p099, 99); check(p100, 100); check(p101, 101); check(p102, 102)
|
||||
check(p103, 103); check(p104, 104); check(p105, 105); check(p106, 106); check(p107, 107); check(p108, 108)
|
||||
check(p109, 109); check(p110, 110); check(p111, 111); check(p112, 112); check(p113, 113); check(p114, 114)
|
||||
check(p115, 115); check(p116, 116); check(p117, 117); check(p118, 118); check(p119, 119); check(p120, 120)
|
||||
check(p121, 121); check(p122, 122); check(p123, 123); check(p124, 124); check(p125, 125); check(p126, 126)
|
||||
check(p127, 127); check(p128, 128); check(p129, 129); check(p130, 130); check(p131, 131); check(p132, 132)
|
||||
check(p133, 133); check(p134, 134); check(p135, 135); check(p136, 136); check(p137, 137); check(p138, 138)
|
||||
check(p139, 139); check(p140, 140); check(p141, 141); check(p142, 142); check(p143, 143); check(p144, 144)
|
||||
check(p145, 145); check(p146, 146); check(p147, 147); check(p148, 148); check(p149, 149); check(p150, 150)
|
||||
check(p151, 151); check(p152, 152); check(p153, 153); check(p154, 154); check(p155, 155); check(p156, 156)
|
||||
check(p157, 157); check(p158, 158); check(p159, 159); check(p160, 160); check(p161, 161); check(p162, 162)
|
||||
check(p163, 163); check(p164, 164); check(p165, 165); check(p166, 166); check(p167, 167); check(p168, 168)
|
||||
check(p169, 169); check(p170, 170); check(p171, 171); check(p172, 172); check(p173, 173); check(p174, 174)
|
||||
check(p175, 175); check(p176, 176); check(p177, 177); check(p178, 178); check(p179, 179); check(p180, 180)
|
||||
check(p181, 181); check(p182, 182); check(p183, 183); check(p184, 184); check(p185, 185); check(p186, 186)
|
||||
check(p187, 187); check(p188, 188); check(p189, 189); check(p190, 190); check(p191, 191); check(p192, 192)
|
||||
check(p193, 193); check(p194, 194); check(p195, 195); check(p196, 196); check(p197, 197); check(p198, 198)
|
||||
check(p199, 199); check(p200, 200); check(p201, 201); check(p202, 202); check(p203, 203); check(p204, 204)
|
||||
check(p205, 205); check(p206, 206); check(p207, 207); check(p208, 208); check(p209, 209); check(p210, 210)
|
||||
check(p211, 211); check(p212, 212); check(p213, 213); check(p214, 214); check(p215, 215); check(p216, 216)
|
||||
check(p217, 217); check(p218, 218); check(p219, 219); check(p220, 220); check(p221, 221); check(p222, 222)
|
||||
check(p223, 223); check(p224, 224); check(p225, 225); check(p226, 226); check(p227, 227); check(p228, 228)
|
||||
check(p229, 229); check(p230, 230); check(p231, 231); check(p232, 232); check(p233, 233); check(p234, 234)
|
||||
check(p235, 235); check(p236, 236); check(p237, 237); check(p238, 238); check(p239, 239); check(p240, 240)
|
||||
check(p241, 241); check(p242, 242); check(p243, 243); check(p244, 244); check(p245, 245); check(p246, 246)
|
||||
check(p247, 247); check(p248, 248); check(p249, 249); check(p250, 250); check(p251, 251); check(p252, 252)
|
||||
check(p253, 253); check(p254, 254)
|
||||
}
|
||||
|
||||
private fun check(a: A, value: Int) {
|
||||
if (a.value != value) {
|
||||
throw AssertionError("Expected $value, actual ${a.value}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val ref = A(0)::lmao
|
||||
|
||||
// for (i in 1..254) { print("A($i), "); if (i % 12 == 0) println() }; println()
|
||||
ref(
|
||||
A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), A(11), A(12),
|
||||
A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20), A(21), A(22), A(23), A(24),
|
||||
A(25), A(26), A(27), A(28), A(29), A(30), A(31), A(32), A(33), A(34), A(35), A(36),
|
||||
A(37), A(38), A(39), A(40), A(41), A(42), A(43), A(44), A(45), A(46), A(47), A(48),
|
||||
A(49), A(50), A(51), A(52), A(53), A(54), A(55), A(56), A(57), A(58), A(59), A(60),
|
||||
A(61), A(62), A(63), A(64), A(65), A(66), A(67), A(68), A(69), A(70), A(71), A(72),
|
||||
A(73), A(74), A(75), A(76), A(77), A(78), A(79), A(80), A(81), A(82), A(83), A(84),
|
||||
A(85), A(86), A(87), A(88), A(89), A(90), A(91), A(92), A(93), A(94), A(95), A(96),
|
||||
A(97), A(98), A(99), A(100), A(101), A(102), A(103), A(104), A(105), A(106), A(107), A(108),
|
||||
A(109), A(110), A(111), A(112), A(113), A(114), A(115), A(116), A(117), A(118), A(119), A(120),
|
||||
A(121), A(122), A(123), A(124), A(125), A(126), A(127), A(128), A(129), A(130), A(131), A(132),
|
||||
A(133), A(134), A(135), A(136), A(137), A(138), A(139), A(140), A(141), A(142), A(143), A(144),
|
||||
A(145), A(146), A(147), A(148), A(149), A(150), A(151), A(152), A(153), A(154), A(155), A(156),
|
||||
A(157), A(158), A(159), A(160), A(161), A(162), A(163), A(164), A(165), A(166), A(167), A(168),
|
||||
A(169), A(170), A(171), A(172), A(173), A(174), A(175), A(176), A(177), A(178), A(179), A(180),
|
||||
A(181), A(182), A(183), A(184), A(185), A(186), A(187), A(188), A(189), A(190), A(191), A(192),
|
||||
A(193), A(194), A(195), A(196), A(197), A(198), A(199), A(200), A(201), A(202), A(203), A(204),
|
||||
A(205), A(206), A(207), A(208), A(209), A(210), A(211), A(212), A(213), A(214), A(215), A(216),
|
||||
A(217), A(218), A(219), A(220), A(221), A(222), A(223), A(224), A(225), A(226), A(227), A(228),
|
||||
A(229), A(230), A(231), A(232), A(233), A(234), A(235), A(236), A(237), A(238), A(239), A(240),
|
||||
A(241), A(242), A(243), A(244), A(245), A(246), A(247), A(248), A(249), A(250), A(251), A(252),
|
||||
A(253), A(254)
|
||||
)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS
|
||||
|
||||
class A
|
||||
|
||||
fun foo(
|
||||
p00: A, p01: A, p02: A, p03: A, p04: A, p05: A, p06: A, p07: A, p08: A, p09: A,
|
||||
p10: A, p11: A, p12: A, p13: A, p14: A, p15: A, p16: A, p17: A, p18: A, p19: A,
|
||||
p20: A, p21: A, p22: A, p23: A, p24: A, p25: A, p26: A, p27: A, p28: A, p29: A
|
||||
) {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val ref = ::foo
|
||||
if (ref is Function0<*>) return "Fail 0"
|
||||
if (ref is Function1<*, *>) return "Fail 1"
|
||||
if (ref !is Function30<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>) return "Fail 30"
|
||||
if (ref is Function31<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>) return "Fail 31"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
class A
|
||||
|
||||
fun foo(
|
||||
p00: A, p01: A, p02: A, p03: A, p04: A, p05: A, p06: A, p07: A, p08: A, p09: A,
|
||||
p10: A, p11: A, p12: A, p13: A, p14: A, p15: A, p16: A, p17: A, p18: A, p19: A,
|
||||
p20: A, p21: A, p22: A, p23: A, p24: A, p25: A, p26: A, p27: A, p28: A, p29: A
|
||||
): String {
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val ref = ::foo
|
||||
|
||||
val a = A()
|
||||
return ref(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)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
class A(val value: Int)
|
||||
|
||||
private fun check(actual: A, expected: Int) {
|
||||
if (expected != actual.value) {
|
||||
throw AssertionError("Expected $expected, actual ${actual.value}")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val l = {
|
||||
p00: A, p01: A, p02: A, p03: A, p04: A, p05: A, p06: A, p07: A, p08: A, p09: A,
|
||||
p10: A, p11: A, p12: A, p13: A, p14: A, p15: A, p16: A, p17: A, p18: A, p19: A,
|
||||
p20: A, p21: A, p22: A, p23: A, p24: A, p25: A, p26: A, p27: A, p28: A, p29: A ->
|
||||
check(p00, 0)
|
||||
check(p01, 1)
|
||||
check(p02, 2)
|
||||
check(p03, 3)
|
||||
check(p04, 4)
|
||||
check(p05, 5)
|
||||
check(p06, 6)
|
||||
check(p07, 7)
|
||||
check(p08, 8)
|
||||
check(p09, 9)
|
||||
check(p10, 10)
|
||||
check(p11, 11)
|
||||
check(p12, 12)
|
||||
check(p13, 13)
|
||||
check(p14, 14)
|
||||
check(p15, 15)
|
||||
check(p16, 16)
|
||||
check(p17, 17)
|
||||
check(p18, 18)
|
||||
check(p19, 19)
|
||||
check(p20, 20)
|
||||
check(p21, 21)
|
||||
check(p22, 22)
|
||||
check(p23, 23)
|
||||
check(p24, 24)
|
||||
check(p25, 25)
|
||||
check(p26, 26)
|
||||
check(p27, 27)
|
||||
check(p28, 28)
|
||||
check(p29, 29)
|
||||
"OK"
|
||||
}
|
||||
|
||||
return l(
|
||||
A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9),
|
||||
A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19),
|
||||
A(20), A(21), A(22), A(23), A(24), A(25), A(26), A(27), A(28), A(29)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// WITH_RUNTIME
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: J.java
|
||||
|
||||
// import kotlin.jvm.functions.Arity;
|
||||
import kotlin.jvm.functions.FunctionN;
|
||||
|
||||
public class J {
|
||||
// TODO: uncomment arity as soon as Arity is introduced
|
||||
// @Arity(30)
|
||||
public static final FunctionN<String> FIELD = new FunctionN<String>() {
|
||||
@Override
|
||||
public String invoke(Object... args) {
|
||||
return "OK";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArity() {
|
||||
return 30;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: uncomment arity as soon as Arity is introduced
|
||||
// @Arity(30)
|
||||
public static FunctionN<String> getViaMethod() {
|
||||
return FIELD;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: K.kt
|
||||
|
||||
class A
|
||||
|
||||
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()
|
||||
return 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)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val f = J.FIELD as Function30<
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
String>
|
||||
if (f !is Function30<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>) return "Fail field 30"
|
||||
if (f is Function31<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>) return "Fail field 31"
|
||||
if (call(f) != "OK") return "Fail field call"
|
||||
|
||||
val m = J.getViaMethod() as Function30<
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?, Any?,
|
||||
String>
|
||||
if (m !is Function30<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>) return "Fail method 30"
|
||||
if (m is Function31<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>) return "Fail method 31"
|
||||
|
||||
return call(m)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Implementing function interface is prohibited in JavaScript
|
||||
// IGNORE_BACKEND: JS_IR, JS
|
||||
|
||||
class A(val value: String)
|
||||
|
||||
class Fun : (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, A, A, A, A, A, A, A, A, A, A, A, A) -> String {
|
||||
override fun invoke(
|
||||
p1: A, p2: A, p3: A, p4: A, p5: A, p6: A, p7: A, p8: A, p9: A,
|
||||
p10: A, p11: A, p12: A, p13: A, p14: A, p15: A, p16: A, p17: A, p18: A, p19: A,
|
||||
p20: A, p21: A, p22: A, p23: A, p24: A, p25: A, p26: A, p27: A, p28: A, p29: A,
|
||||
p30: A, p31: A, p32: A, p33: A, p34: A, p35: A, p36: A, p37: A, p38: A, p39: A,
|
||||
p40: A, p41: A, p42: A
|
||||
): String {
|
||||
return p21.value + p32.value
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A("")
|
||||
val f = Fun()
|
||||
return f(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, A("O"), a, a, a, a, a, a, a, a, a, a, A("K"), a, a, a, a, a, a, a, a, a, a)
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: Test.java
|
||||
|
||||
// import kotlin.jvm.functions.Arity;
|
||||
import kotlin.jvm.functions.FunctionN;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Test {
|
||||
public static final int N = 30;
|
||||
|
||||
// TODO: uncomment arity as soon as Arity is introduced
|
||||
public static void test(/* @Arity(N) */ FunctionN<Object> f) {
|
||||
Object[] args = new Object[N];
|
||||
Object o = new Object();
|
||||
Arrays.fill(args, o);
|
||||
for (int i = 0; i < N; i++) {
|
||||
args[i] = null;
|
||||
try {
|
||||
f.invoke(args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// OK
|
||||
continue;
|
||||
} catch (Throwable e) {
|
||||
throw new AssertionError(
|
||||
"Incorrect exception (IllegalArgumentException expected): " + e.getClass().getName() + ", parameter index = " + i,
|
||||
e
|
||||
);
|
||||
} finally {
|
||||
args[i] = o;
|
||||
}
|
||||
throw new AssertionError("IllegalArgumentException expected, but nothing was thrown, parameter index = " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
fun f(
|
||||
p01: Any, p02: Any, p03: Any, p04: Any, p05: Any, p06: Any, p07: Any, p08: Any, p09: Any, p10: Any,
|
||||
p11: Any, p12: Any, p13: Any, p14: Any, p15: Any, p16: Any, p17: Any, p18: Any, p19: Any, p20: Any,
|
||||
p21: Any, p22: Any, p23: Any, p24: Any, p25: Any, p26: Any, p27: Any, p28: Any, p29: Any, p30: Any
|
||||
): Any = Any()
|
||||
|
||||
fun Any.g(
|
||||
p02: Any, p03: Any, p04: Any, p05: Any, p06: Any, p07: Any, p08: Any, p09: Any, p10: Any,
|
||||
p11: Any, p12: Any, p13: Any, p14: Any, p15: Any, p16: Any, p17: Any, p18: Any, p19: Any, p20: Any,
|
||||
p21: Any, p22: Any, p23: Any, p24: Any, p25: Any, p26: Any, p27: Any, p28: Any, p29: Any, p30: Any
|
||||
): Any = Any()
|
||||
|
||||
fun box(): String {
|
||||
Test.test(::f as kotlin.jvm.functions.FunctionN<Any>)
|
||||
Test.test(Any::g as kotlin.jvm.functions.FunctionN<Any>)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE
|
||||
// WITH_REFLECT
|
||||
|
||||
class A {
|
||||
fun foo(
|
||||
p00: A, p01: A, p02: A, p03: A, p04: A, p05: A, p06: A, p07: A, p08: A, p09: A,
|
||||
p10: A, p11: A, p12: A, p13: A, p14: A, p15: A, p16: A, p17: A, p18: A, p19: A,
|
||||
p20: A, p21: A, p22: A, p23: A, p24: A, p25: A, p26: A, p27: A, p28: A, p29: String
|
||||
): String {
|
||||
return p29
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
val o = A::foo.call(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, "O")
|
||||
|
||||
val foo = A::class.members.single { it.name == "foo" }
|
||||
val k = foo.call(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, "K")
|
||||
|
||||
return o + k
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class A
|
||||
|
||||
data class BigDataClass(
|
||||
val p00: A, val p01: A, val p02: A, val p03: A, val p04: A, val p05: A, val p06: A, val p07: A, val p08: A, val p09: A,
|
||||
val p10: A, val p11: A, val p12: A, val p13: A, val p14: A, val p15: A, val p16: A, val p17: A, val p18: A, val p19: A,
|
||||
val p20: A, val p21: A, val p22: A, val p23: A, val p24: A, val p25: A, val p26: A, val p27: A, val p28: A, val p29: A
|
||||
)
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(
|
||||
"[null, p00, p01, p02, p03, p04, p05, p06, p07, p08, p09, p10, p11, p12, p13, p14, " +
|
||||
"p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29]",
|
||||
BigDataClass::copy.parameters.map { it.name }.toString()
|
||||
)
|
||||
return "OK"
|
||||
}
|
||||
Generated
+63
@@ -10275,6 +10275,54 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class BigArity extends AbstractIrBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBigArity() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/bigArity"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("callWithIncorrectNumberOfArguments.kt")
|
||||
public void testCallWithIncorrectNumberOfArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/callWithIncorrectNumberOfArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("function255.kt")
|
||||
public void testFunction255() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/function255.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("instanceOfCallableReference.kt")
|
||||
public void testInstanceOfCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/instanceOfCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeCallableReference.kt")
|
||||
public void testInvokeCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeLambda.kt")
|
||||
public void testInvokeLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaLambda.kt")
|
||||
public void testJavaLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/javaLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subclass.kt")
|
||||
public void testSubclass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/subclass.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/functionExpression")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -11687,6 +11735,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/extensionReceiverParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionWithBigArity.kt")
|
||||
public void testFunctionWithBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/functionWithBigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11.kt")
|
||||
public void testIncWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/incWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11.kt");
|
||||
@@ -16649,6 +16702,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/call"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callInstanceJavaMethod.kt")
|
||||
public void testCallInstanceJavaMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/callInstanceJavaMethod.kt");
|
||||
@@ -18085,6 +18143,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/parameters"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("boundInnerClassConstructor.kt")
|
||||
public void testBoundInnerClassConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/boundInnerClassConstructor.kt");
|
||||
|
||||
+63
@@ -10275,6 +10275,54 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class BigArity extends AbstractBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBigArity() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/bigArity"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("callWithIncorrectNumberOfArguments.kt")
|
||||
public void testCallWithIncorrectNumberOfArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/callWithIncorrectNumberOfArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("function255.kt")
|
||||
public void testFunction255() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/function255.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("instanceOfCallableReference.kt")
|
||||
public void testInstanceOfCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/instanceOfCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeCallableReference.kt")
|
||||
public void testInvokeCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeLambda.kt")
|
||||
public void testInvokeLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaLambda.kt")
|
||||
public void testJavaLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/javaLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subclass.kt")
|
||||
public void testSubclass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/subclass.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/functionExpression")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -11687,6 +11735,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/extensionReceiverParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionWithBigArity.kt")
|
||||
public void testFunctionWithBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/functionWithBigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11.kt")
|
||||
public void testIncWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/incWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11.kt");
|
||||
@@ -16649,6 +16702,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/call"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callInstanceJavaMethod.kt")
|
||||
public void testCallInstanceJavaMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/callInstanceJavaMethod.kt");
|
||||
@@ -18085,6 +18143,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/parameters"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("boundInnerClassConstructor.kt")
|
||||
public void testBoundInnerClassConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/boundInnerClassConstructor.kt");
|
||||
|
||||
+63
@@ -10275,6 +10275,54 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class BigArity extends AbstractLightAnalysisModeTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBigArity() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/bigArity"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("callWithIncorrectNumberOfArguments.kt")
|
||||
public void testCallWithIncorrectNumberOfArguments() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/callWithIncorrectNumberOfArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("function255.kt")
|
||||
public void testFunction255() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/function255.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("instanceOfCallableReference.kt")
|
||||
public void testInstanceOfCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/instanceOfCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeCallableReference.kt")
|
||||
public void testInvokeCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeLambda.kt")
|
||||
public void testInvokeLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaLambda.kt")
|
||||
public void testJavaLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/javaLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subclass.kt")
|
||||
public void testSubclass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/subclass.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/functionExpression")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -11687,6 +11735,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/extensionReceiverParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionWithBigArity.kt")
|
||||
public void testFunctionWithBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/functionWithBigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11.kt")
|
||||
public void testIncWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/incWithNullabilityAssertionOnExtensionReceiverInPrivateOperator_lv11.kt");
|
||||
@@ -16649,6 +16702,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/call"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callInstanceJavaMethod.kt")
|
||||
public void testCallInstanceJavaMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/callInstanceJavaMethod.kt");
|
||||
@@ -18085,6 +18143,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/parameters"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("boundInnerClassConstructor.kt")
|
||||
public void testBoundInnerClassConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/boundInnerClassConstructor.kt");
|
||||
|
||||
+34
-12
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
|
||||
import org.jetbrains.kotlin.builtins.PlatformToKotlinClassMap
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.name.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -21,6 +22,14 @@ import org.jetbrains.kotlin.types.TypeUtils
|
||||
import java.util.*
|
||||
|
||||
object JavaToKotlinClassMap : PlatformToKotlinClassMap {
|
||||
private val NUMBERED_FUNCTION_PREFIX =
|
||||
FunctionClassDescriptor.Kind.Function.packageFqName.toString() + "." + FunctionClassDescriptor.Kind.Function.classNamePrefix
|
||||
private val NUMBERED_K_FUNCTION_PREFIX =
|
||||
FunctionClassDescriptor.Kind.KFunction.packageFqName.toString() + "." + FunctionClassDescriptor.Kind.KFunction.classNamePrefix
|
||||
|
||||
private val FUNCTION_N_CLASS_ID = ClassId.topLevel(FqName("kotlin.jvm.functions.FunctionN"))
|
||||
private val FUNCTION_N_FQ_NAME = FUNCTION_N_CLASS_ID.asSingleFqName()
|
||||
private val K_FUNCTION_CLASS_ID = ClassId.topLevel(FqName("kotlin.reflect.KFunction"))
|
||||
|
||||
private val javaToKotlin = HashMap<FqNameUnsafe, ClassId>()
|
||||
private val kotlinToJava = HashMap<FqNameUnsafe, ClassId>()
|
||||
@@ -82,17 +91,14 @@ object JavaToKotlinClassMap : PlatformToKotlinClassMap {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: support also functions with >= 23 parameters
|
||||
val kFunction = FunctionClassDescriptor.Kind.KFunction
|
||||
val kFun = kFunction.packageFqName.toString() + "." + kFunction.classNamePrefix
|
||||
for (i in 0..22) {
|
||||
add(ClassId.topLevel(FqName("kotlin.jvm.functions.Function" + i)), KotlinBuiltIns.getFunctionClassId(i))
|
||||
addKotlinToJava(FqName(kFun + i), ClassId.topLevel(FqName(kFun)))
|
||||
for (i in 0 until FunctionInvokeDescriptor.BIG_ARITY) {
|
||||
add(ClassId.topLevel(FqName("kotlin.jvm.functions.Function$i")), KotlinBuiltIns.getFunctionClassId(i))
|
||||
addKotlinToJava(FqName(NUMBERED_K_FUNCTION_PREFIX + i), K_FUNCTION_CLASS_ID)
|
||||
}
|
||||
for (i in 0 until 22) {
|
||||
for (i in 0 until FunctionInvokeDescriptor.BIG_ARITY - 1) {
|
||||
val kSuspendFunction = FunctionClassDescriptor.Kind.KSuspendFunction
|
||||
val kSuspendFun = kSuspendFunction.packageFqName.toString() + "." + kSuspendFunction.classNamePrefix
|
||||
addKotlinToJava(FqName(kSuspendFun + i), ClassId.topLevel(FqName(kFun)))
|
||||
addKotlinToJava(FqName(kSuspendFun + i), K_FUNCTION_CLASS_ID)
|
||||
}
|
||||
|
||||
addKotlinToJava(FQ_NAMES.nothing.toSafe(), classId(Void::class.java))
|
||||
@@ -107,13 +113,16 @@ object JavaToKotlinClassMap : PlatformToKotlinClassMap {
|
||||
* java.util.Map.Entry -> kotlin.Map.Entry
|
||||
* java.lang.Void -> null
|
||||
* kotlin.jvm.functions.Function3 -> kotlin.Function3
|
||||
* kotlin.jvm.functions.FunctionN -> null // Without a type annotation like @Arity(n), it's impossible to find out arity
|
||||
*/
|
||||
fun mapJavaToKotlin(fqName: FqName): ClassId? {
|
||||
return javaToKotlin[fqName.toUnsafe()]
|
||||
}
|
||||
|
||||
fun mapJavaToKotlin(fqName: FqName, builtIns: KotlinBuiltIns): ClassDescriptor? {
|
||||
val kotlinClassId = mapJavaToKotlin(fqName)
|
||||
fun mapJavaToKotlin(fqName: FqName, builtIns: KotlinBuiltIns, functionTypeArity: Int? = null): ClassDescriptor? {
|
||||
val kotlinClassId =
|
||||
if (functionTypeArity != null && fqName == FUNCTION_N_FQ_NAME) KotlinBuiltIns.getFunctionClassId(functionTypeArity)
|
||||
else mapJavaToKotlin(fqName)
|
||||
return if (kotlinClassId != null) builtIns.getBuiltInClassByFqName(kotlinClassId.asSingleFqName()) else null
|
||||
}
|
||||
|
||||
@@ -125,10 +134,23 @@ object JavaToKotlinClassMap : PlatformToKotlinClassMap {
|
||||
* kotlin.Nothing -> java.lang.Void
|
||||
* kotlin.IntArray -> null
|
||||
* kotlin.Function3 -> kotlin.jvm.functions.Function3
|
||||
* kotlin.Function42 -> kotlin.jvm.functions.FunctionN
|
||||
* kotlin.reflect.KFunction3 -> kotlin.reflect.KFunction
|
||||
* kotlin.reflect.KFunction42 -> kotlin.reflect.KFunction
|
||||
*/
|
||||
fun mapKotlinToJava(kotlinFqName: FqNameUnsafe): ClassId? {
|
||||
return kotlinToJava[kotlinFqName]
|
||||
fun mapKotlinToJava(kotlinFqName: FqNameUnsafe): ClassId? = when {
|
||||
isKotlinFunctionWithBigArity(kotlinFqName, NUMBERED_FUNCTION_PREFIX) -> FUNCTION_N_CLASS_ID
|
||||
isKotlinFunctionWithBigArity(kotlinFqName, NUMBERED_K_FUNCTION_PREFIX) -> K_FUNCTION_CLASS_ID
|
||||
else -> kotlinToJava[kotlinFqName]
|
||||
}
|
||||
|
||||
private fun isKotlinFunctionWithBigArity(kotlinFqName: FqNameUnsafe, prefix: String): Boolean {
|
||||
val arityString = kotlinFqName.asString().substringAfter(prefix, "")
|
||||
if (arityString.isNotEmpty() && !arityString.startsWith('0')) {
|
||||
val arity = arityString.toIntOrNull()
|
||||
return arity != null && arity >= FunctionInvokeDescriptor.BIG_ARITY
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun addMapping(platformMutabilityMapping: PlatformMutabilityMapping) {
|
||||
|
||||
+15
@@ -46,6 +46,18 @@ class FunctionInvokeDescriptor private constructor(
|
||||
this.setHasStableParameterNames(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this `invoke` has so much parameters that it makes sense to wrap them into array and make this function have a single
|
||||
* `vararg Any?` parameter in the binaries, on platforms where function types are represented as separate classes (JVM, Native).
|
||||
*
|
||||
* For example, on JVM there are 23 function classes with the fixed number of parameters (`Function0` ... `Function22`), and another
|
||||
* class representing the function with big arity, with a variable number of parameters (`FunctionN`). Whenever `invoke` of a function
|
||||
* type with big arity is called, the JVM back-end wraps all arguments into an array and passes it to `FunctionN.invoke`.
|
||||
*/
|
||||
@get:JvmName("hasBigArity")
|
||||
val hasBigArity: Boolean
|
||||
get() = valueParameters.size >= BIG_ARITY
|
||||
|
||||
override fun doSubstitute(configuration: CopyConfiguration): FunctionDescriptor? {
|
||||
val substituted = super.doSubstitute(configuration) as FunctionInvokeDescriptor? ?: return null
|
||||
if (substituted.valueParameters.none { it.type.extractParameterNameFromFunctionTypeArgument() != null }) return substituted
|
||||
@@ -96,6 +108,9 @@ class FunctionInvokeDescriptor private constructor(
|
||||
}
|
||||
|
||||
companion object Factory {
|
||||
/** @see hasBigArity */
|
||||
const val BIG_ARITY = 23
|
||||
|
||||
fun create(functionClass: FunctionClassDescriptor, isSuspend: Boolean): FunctionInvokeDescriptor {
|
||||
val typeParameters = functionClass.declaredTypeParameters
|
||||
|
||||
|
||||
+48
@@ -8935,6 +8935,44 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class BigArity extends AbstractIrJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBigArity() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/bigArity"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("function255.kt")
|
||||
public void testFunction255() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/function255.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("instanceOfCallableReference.kt")
|
||||
public void testInstanceOfCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/instanceOfCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeCallableReference.kt")
|
||||
public void testInvokeCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeLambda.kt")
|
||||
public void testInvokeLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subclass.kt")
|
||||
public void testSubclass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/subclass.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/functionExpression")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -14944,6 +14982,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/call"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callInstanceJavaMethod.kt")
|
||||
public void testCallInstanceJavaMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/callInstanceJavaMethod.kt");
|
||||
@@ -16365,6 +16408,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/parameters"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("boundInnerClassConstructor.kt")
|
||||
public void testBoundInnerClassConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/boundInnerClassConstructor.kt");
|
||||
|
||||
+48
@@ -9930,6 +9930,44 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class BigArity extends AbstractJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBigArity() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/functions/bigArity"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("function255.kt")
|
||||
public void testFunction255() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/function255.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("instanceOfCallableReference.kt")
|
||||
public void testInstanceOfCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/instanceOfCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeCallableReference.kt")
|
||||
public void testInvokeCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeCallableReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeLambda.kt")
|
||||
public void testInvokeLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("subclass.kt")
|
||||
public void testSubclass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/bigArity/subclass.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/functionExpression")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -15939,6 +15977,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/call"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callInstanceJavaMethod.kt")
|
||||
public void testCallInstanceJavaMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/call/callInstanceJavaMethod.kt");
|
||||
@@ -17360,6 +17403,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/parameters"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bigArity.kt")
|
||||
public void testBigArity() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/bigArity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("boundInnerClassConstructor.kt")
|
||||
public void testBoundInnerClassConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/parameters/boundInnerClassConstructor.kt");
|
||||
|
||||
Reference in New Issue
Block a user