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
This commit is contained in:
Alexander Udalov
2016-09-05 16:38:12 +03:00
parent 6845d0958a
commit 90eafe0d71
7 changed files with 67 additions and 14 deletions
@@ -373,8 +373,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
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);
}
@@ -525,7 +525,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
// TODO: generate the container once and save to a local field instead (KT-10495)
ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state);
iv.aconst(property.getName().asString());
iv.aconst(PropertyReferenceCodegen.getPropertyReferenceSignature(property, state));
PropertyReferenceCodegen.generateCallableReferenceSignature(iv, property, state);
iv.invokespecial(
implType.getInternalName(), "<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false
@@ -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