From 49de52e7ef97ee7a8aee5ca2cfe853debca0bfad Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 15 Dec 2016 14:25:30 +0300 Subject: [PATCH] Fix kotlinFunction for inline reified methods in reflection Inline functions with reified type parameters are generated as private (see AsmUtil.specialCaseVisibility), so we should treat them as "declared" in reflection to look them up via getDeclaredMethod, not getMethod #KT-14721 Fixed --- .../reflection/mapping/inlineReifiedFun.kt | 23 +++++++++++++++++++ .../reflection/mapping/inlineReifiedFun.txt | 11 +++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 6 +++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++++ ...LightAnalysisModeCodegenTestGenerated.java | 6 +++++ .../reflect/jvm/internal/KFunctionImpl.kt | 7 +++++- .../semantics/JsCodegenBoxTestGenerated.java | 12 ++++++++++ 7 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt create mode 100644 compiler/testData/codegen/light-analysis/reflection/mapping/inlineReifiedFun.txt diff --git a/compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt b/compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt new file mode 100644 index 00000000000..b1ca36b546e --- /dev/null +++ b/compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt @@ -0,0 +1,23 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.* +import kotlin.reflect.jvm.* +import kotlin.test.assertEquals + +inline fun f() = 1 + +fun g() {} + +class Foo { + inline fun h(t: T) = 1 +} + +fun box(): String { + assertEquals(::g, ::g.javaMethod!!.kotlinFunction) + + val h = Foo::class.members.single { it.name == "h" } as KFunction<*> + assertEquals(h, h.javaMethod!!.kotlinFunction) + + return "OK" +} diff --git a/compiler/testData/codegen/light-analysis/reflection/mapping/inlineReifiedFun.txt b/compiler/testData/codegen/light-analysis/reflection/mapping/inlineReifiedFun.txt new file mode 100644 index 00000000000..5edddce3b1a --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/mapping/inlineReifiedFun.txt @@ -0,0 +1,11 @@ +public final class Foo { + public method (): void + private final method h(p0: java.lang.Object): int +} + + +public final class InlineReifiedFunKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + private final static method f(): int + public final static method g(): void +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 15dca3f37cc..5adfc6724ad 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13492,6 +13492,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("inlineReifiedFun.kt") + public void testInlineReifiedFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt"); + doTest(fileName); + } + @TestMetadata("mappedClassIsEqualToClassLiteral.kt") public void testMappedClassIsEqualToClassLiteral() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index fc8603ca575..e9d327835f1 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13492,6 +13492,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("inlineReifiedFun.kt") + public void testInlineReifiedFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt"); + doTest(fileName); + } + @TestMetadata("mappedClassIsEqualToClassLiteral.kt") public void testMappedClassIsEqualToClassLiteral() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java index c4d3cc2556e..a39d2307ac6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java @@ -13492,6 +13492,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis doTest(fileName); } + @TestMetadata("inlineReifiedFun.kt") + public void testInlineReifiedFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt"); + doTest(fileName); + } + @TestMetadata("mappedClassIsEqualToClassLiteral.kt") public void testMappedClassIsEqualToClassLiteral() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt index abed0a8e94c..649e3785802 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt @@ -19,6 +19,7 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.annotations.isInlineOnlyOrReified import java.lang.reflect.Constructor import java.lang.reflect.Member import java.lang.reflect.Method @@ -58,7 +59,11 @@ internal class KFunctionImpl private constructor( override val name: String get() = descriptor.name.asString() - private fun isDeclared(): Boolean = Visibilities.isPrivate(descriptor.visibility) + private fun isPrivateInBytecode(): Boolean = + Visibilities.isPrivate(descriptor.visibility) || + descriptor.isInlineOnlyOrReified() + + private fun isDeclared(): Boolean = isPrivateInBytecode() override val caller: FunctionCaller<*> by ReflectProperties.lazySoft caller@ { val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 4bbd0617ed3..81ab72d3bb1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -16697,6 +16697,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); } + @TestMetadata("inlineReifiedFun.kt") + public void testInlineReifiedFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/inlineReifiedFun.kt"); + try { + doTest(fileName); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + @TestMetadata("mappedClassIsEqualToClassLiteral.kt") public void testMappedClassIsEqualToClassLiteral() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt");