From 90eafe0d7133b0b65986b1b92728aa2464cd3246 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 5 Sep 2016 16:38:12 +0300 Subject: [PATCH] Fix reflective access on overridden generic property reference Generation of callable reference's signature in codegen should use the same mechanism for obtaining the signature as the runtime in RuntimeTypeMapper, namely DescriptorUtils.unwrapFakeOverride(...).original #KT-13700 Fixed --- .../kotlin/codegen/ClosureCodegen.java | 3 +-- .../kotlin/codegen/MemberCodegen.java | 2 +- .../codegen/PropertyReferenceCodegen.kt | 22 ++++++++++++------- .../functions/genericOverriddenFunction.kt | 16 ++++++++++++++ .../properties/genericOverriddenProperty.kt | 17 ++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 12 ++++++++++ .../kotlin/resolve/DescriptorUtils.java | 9 +++++--- 7 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 compiler/testData/codegen/box/reflection/functions/genericOverriddenFunction.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/genericOverriddenProperty.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index e734f00ac21..e401e101755 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -373,8 +373,7 @@ public class ClosureCodegen extends MemberCodegen { if (generateBody) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); - Method method = typeMapper.mapAsmMethod(descriptor.getOriginal()); - iv.aconst(method.getName() + method.getDescriptor()); + PropertyReferenceCodegen.generateCallableReferenceSignature(iv, descriptor, state); iv.areturn(JAVA_STRING_TYPE); FunctionCodegen.endVisit(iv, "function reference getSignature", element); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 20789073dd0..38cdc7ca617 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -525,7 +525,7 @@ public abstract class MemberCodegen", Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index 03b02ad1dba..e36dc3e3f47 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.DescriptorFactory +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.PropertyImportedFromObject import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* @@ -110,7 +111,7 @@ class PropertyReferenceCodegen( } generateMethod("property reference getSignature", ACC_PUBLIC, method("getSignature", JAVA_STRING_TYPE)) { - aconst(getPropertyReferenceSignature(target as VariableDescriptorWithAccessors, state)) + generateCallableReferenceSignature(this, target, state) } if (!isLocalDelegatedProperty) { @@ -180,14 +181,19 @@ class PropertyReferenceCodegen( companion object { @JvmStatic - fun getPropertyReferenceSignature(property: VariableDescriptorWithAccessors, state: GenerationState): String { - val getter = - property.getter ?: DescriptorFactory.createDefaultGetter(property as PropertyDescriptor, Annotations.EMPTY).apply { - initialize(property.type) + fun generateCallableReferenceSignature(iv: InstructionAdapter, callable: CallableDescriptor, state: GenerationState) { + val accessor = when (callable) { + is FunctionDescriptor -> callable + is VariableDescriptorWithAccessors -> + callable.getter ?: + DescriptorFactory.createDefaultGetter(callable as PropertyDescriptor, Annotations.EMPTY).apply { + initialize(callable.type) } - - val method = state.typeMapper.mapAsmMethod(getter.original) - return method.name + method.descriptor + else -> error("Unsupported callable reference: $callable") + } + val declaration = DescriptorUtils.unwrapFakeOverride(accessor).original + val method = state.typeMapper.mapAsmMethod(declaration) + iv.aconst(method.name + method.descriptor) } @JvmStatic diff --git a/compiler/testData/codegen/box/reflection/functions/genericOverriddenFunction.kt b/compiler/testData/codegen/box/reflection/functions/genericOverriddenFunction.kt new file mode 100644 index 00000000000..20a2c35921f --- /dev/null +++ b/compiler/testData/codegen/box/reflection/functions/genericOverriddenFunction.kt @@ -0,0 +1,16 @@ +// WITH_REFLECT + +import kotlin.test.assertEquals + +interface H { + fun foo(): T? +} + +interface A : H + +fun box(): String { + assertEquals("A?", A::foo.returnType.toString()) + assertEquals("T?", H::foo.returnType.toString()) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/properties/genericOverriddenProperty.kt b/compiler/testData/codegen/box/reflection/properties/genericOverriddenProperty.kt new file mode 100644 index 00000000000..bca17295094 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/genericOverriddenProperty.kt @@ -0,0 +1,17 @@ +// WITH_REFLECT +// KT-13700 Exception obtaining descriptor for property reference + +import kotlin.test.assertEquals + +interface H { + val parent : T? +} + +interface A : H + +fun box(): String { + assertEquals("A?", A::parent.returnType.toString()) + assertEquals("T?", H::parent.returnType.toString()) + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 2f22f769cc0..67784063f25 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -12258,6 +12258,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("genericOverriddenFunction.kt") + public void testGenericOverriddenFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/functions/genericOverriddenFunction.kt"); + doTest(fileName); + } + @TestMetadata("javaClassGetFunctions.kt") public void testJavaClassGetFunctions() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/functions/javaClassGetFunctions.kt"); @@ -12999,6 +13005,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("genericOverriddenProperty.kt") + public void testGenericOverriddenProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/genericOverriddenProperty.kt"); + doTest(fileName); + } + @TestMetadata("genericProperty.kt") public void testGenericProperty() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/genericProperty.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index 3a6b4c937e0..8d771b2e39f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -33,7 +33,10 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.StringValue; import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter; import org.jetbrains.kotlin.resolve.scopes.MemberScope; -import org.jetbrains.kotlin.types.*; +import org.jetbrains.kotlin.types.ErrorUtils; +import org.jetbrains.kotlin.types.KotlinType; +import org.jetbrains.kotlin.types.TypeConstructor; +import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import java.util.*; @@ -418,8 +421,8 @@ public class DescriptorUtils { /** * Given a fake override, finds any declaration of it in the overridden descriptors. Keep in mind that there may be many declarations - * of the fake override in the supertypes, this method finds just the only one. - * TODO: probably all call-sites of this method are wrong, they should handle all super-declarations + * of the fake override in the supertypes, this method finds just only one of them. + * TODO: probably some call-sites of this method are wrong, they should handle all super-declarations */ @NotNull @SuppressWarnings("unchecked")