diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index 10b42d208a1..d8906bdf2f7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -34,7 +34,6 @@ import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.psi.JetElement; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorUtils; -import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.expressions.OperatorConventions; import org.jetbrains.org.objectweb.asm.MethodVisitor; @@ -337,8 +336,11 @@ public class ClosureCodegen extends MemberCodegen { iv.load(0, superClassAsmType); - if (superClassAsmType.equals(AsmTypes.LAMBDA)) { - iv.iconst(funDescriptor.getValueParameters().size()); + if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE)) { + int arity = funDescriptor.getValueParameters().size(); + if (funDescriptor.getExtensionReceiverParameter() != null) arity++; + if (funDescriptor.getDispatchReceiverParameter() != null) arity++; + iv.iconst(arity); iv.invokespecial(superClassAsmType.getInternalName(), "", "(I)V", false); } else { diff --git a/compiler/testData/codegen/boxWithStdlib/callableReference/function/getArityViaFunctionImpl.kt b/compiler/testData/codegen/boxWithStdlib/callableReference/function/getArityViaFunctionImpl.kt new file mode 100644 index 00000000000..e89b5abb45a --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/callableReference/function/getArityViaFunctionImpl.kt @@ -0,0 +1,30 @@ +import kotlin.test.assertEquals +import kotlin.jvm.internal.FunctionImpl + +fun test(f: Function<*>, arity: Int) { + assertEquals(arity, (f as FunctionImpl).getArity()) +} + +fun foo(s: String, i: Int) {} +class A { + fun bar(s: String, i: Int) {} +} +fun Double.baz(s: String, i: Int) {} + +fun box(): String { + test(::foo, 2) + test(A::bar, 3) + test(Double::baz, 3) + + test(::box, 0) + + fun local(x: Int) {} + test(::local, 1) + + test(fun(s: String) = s, 1) + test(fun(){}, 0) + test({}, 0) + test({x: Int -> x}, 1) + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index dc090857081..daaab90ea3e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -483,6 +483,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("getArityViaFunctionImpl.kt") + public void testGetArityViaFunctionImpl() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/callableReference/function/getArityViaFunctionImpl.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("innerConstructorFromClass.kt") public void testInnerConstructorFromClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/callableReference/function/innerConstructorFromClass.kt"); diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java index 31ab4de6e60..ac5166b8a1d 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java @@ -24,4 +24,14 @@ public abstract class FunctionReference KMemberFunction, KTopLevelExtensionFunction, KLocalFunction { + private final int arity; + + public FunctionReference(int arity) { + this.arity = arity; + } + + @Override + public int getArity() { + return arity; + } }