diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt index 33766a92562..c132d48516f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -33,6 +33,8 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.org.objectweb.asm.ClassReader +import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.Method import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode @@ -90,10 +92,7 @@ class DefaultLambda( override lateinit var invokeMethod: Method private set - - override val invokeMethodDescriptor: FunctionDescriptor = - parameterDescriptor.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).single() - + override lateinit var invokeMethodDescriptor: FunctionDescriptor override lateinit var capturedVars: List private set @@ -102,6 +101,25 @@ class DefaultLambda( override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) { val classReader = InlineCodegenUtil.buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName) + var isPropertyReference = false + var isFunctionReference = false + classReader.accept(object: ClassVisitor(InlineCodegenUtil.API){ + override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array?) { + isPropertyReference = superName?.startsWith("kotlin/jvm/internal/PropertyReference") ?: false + isFunctionReference = "kotlin/jvm/internal/FunctionReference" == superName + + super.visit(version, access, name, signature, superName, interfaces) + } + }, ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG) + + invokeMethodDescriptor = + parameterDescriptor.type.memberScope + .getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND) + .single() + .let { + //property reference generates erased 'get' method + if (isPropertyReference) it.original else it + } val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs) val constructor = InlineCodegenUtil.getMethodNode( @@ -121,7 +139,7 @@ class DefaultLambda( invokeMethod = Method( - OperatorNameConventions.INVOKE.asString(), + (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(), codegen.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor ) @@ -252,4 +270,4 @@ class ExpressionLambda( SMAPAndMethodNode(methodNode, smap) } } -} +} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt index fd8f4f0b0d6..18b489c2e77 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt @@ -25,7 +25,7 @@ object SMAPParser { } val mapping = - if (source == null || source.isEmpty()) + if (source == null || source.isEmpty() || methodStartLine > methodEndLine) FileMapping.SKIP else FileMapping(source, path).apply { diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromClass.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromClass.kt index f9164fcb0ed..b979f06a998 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromClass.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromClass.kt @@ -3,8 +3,6 @@ // SKIP_INLINE_CHECK_IN: inlineFun$default package test -fun ok() = "OK" - class A(val value: String) { fun ok() = value } diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromObject.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromObject.kt new file mode 100644 index 00000000000..cd1d2d67bd9 --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromObject.kt @@ -0,0 +1,22 @@ +// FILE: 1.kt +// LANGUAGE_VERSION: 1.2 +// SKIP_INLINE_CHECK_IN: inlineFun$default +package test + +fun ok() = "OK" + +object A { + fun ok() = "OK" +} + +inline fun inlineFun(lambda: () -> String = A::ok): String { + return lambda() +} + +// FILE: 2.kt + +import test.* + +fun box(): String { + return inlineFun() +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReference.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReference.kt new file mode 100644 index 00000000000..aaa25f84e3c --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReference.kt @@ -0,0 +1,18 @@ +// FILE: 1.kt +// LANGUAGE_VERSION: 1.2 +// SKIP_INLINE_CHECK_IN: inlineFun$default +package test + +val ok = "OK" + +inline fun inlineFun(lambda: () -> String = ::ok): String { + return lambda() +} + +// FILE: 2.kt + +import test.* + +fun box(): String { + return inlineFun() +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromClass.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromClass.kt new file mode 100644 index 00000000000..ba9f84bcb56 --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromClass.kt @@ -0,0 +1,18 @@ +// FILE: 1.kt +// LANGUAGE_VERSION: 1.2 +// SKIP_INLINE_CHECK_IN: inlineFun$default +package test + +class A(val ok: String) + +inline fun inlineFun(a: A, lambda: (A) -> String = A::ok): String { + return lambda(a) +} + +// FILE: 2.kt + +import test.* + +fun box(): String { + return inlineFun(A("OK")) +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromObject.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromObject.kt new file mode 100644 index 00000000000..e569fdf7d8b --- /dev/null +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromObject.kt @@ -0,0 +1,20 @@ +// FILE: 1.kt +// LANGUAGE_VERSION: 1.2 +// SKIP_INLINE_CHECK_IN: inlineFun$default +package test + +object A { + val ok = "OK" +} + +inline fun inlineFun(lambda: () -> String = A::ok): String { + return lambda() +} + +// FILE: 2.kt + +import test.* + +fun box(): String { + return inlineFun() +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index 1c3e06d8dc4..1b8101a51d8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -979,6 +979,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo doTest(fileName); } + @TestMetadata("functionReferenceFromObject.kt") + public void testFunctionReferenceFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromObject.kt"); + doTest(fileName); + } + @TestMetadata("instanceCapuredInClass.kt") public void testInstanceCapuredInClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt"); @@ -1009,6 +1015,24 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo doTest(fileName); } + @TestMetadata("propertyReference.kt") + public void testPropertyReference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReference.kt"); + doTest(fileName); + } + + @TestMetadata("propertyReferenceFromClass.kt") + public void testPropertyReferenceFromClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromClass.kt"); + doTest(fileName); + } + + @TestMetadata("propertyReferenceFromObject.kt") + public void testPropertyReferenceFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromObject.kt"); + doTest(fileName); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 44c409a0f80..4f93e9cda18 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -979,6 +979,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi doTest(fileName); } + @TestMetadata("functionReferenceFromObject.kt") + public void testFunctionReferenceFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromObject.kt"); + doTest(fileName); + } + @TestMetadata("instanceCapuredInClass.kt") public void testInstanceCapuredInClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt"); @@ -1009,6 +1015,24 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi doTest(fileName); } + @TestMetadata("propertyReference.kt") + public void testPropertyReference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReference.kt"); + doTest(fileName); + } + + @TestMetadata("propertyReferenceFromClass.kt") + public void testPropertyReferenceFromClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromClass.kt"); + doTest(fileName); + } + + @TestMetadata("propertyReferenceFromObject.kt") + public void testPropertyReferenceFromObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromObject.kt"); + doTest(fileName); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt");