From edb8797fa650e8a9908d5ed6dddb1db4e5717843 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Wed, 24 Oct 2012 18:29:31 +0400 Subject: [PATCH] KT-2987 java.lang.AbstractMethodError/java.lang.NoSuchMethodError for delegated class by parameterized parent #KT-2987 Fixed --- .../jet/codegen/FunctionCodegen.java | 31 ++++++++++++------- .../jet/codegen/PropertyCodegen.java | 11 ++++--- .../codegen/classes/typedDelegation.kt | 31 +++++++++++++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 5 +++ 4 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/codegen/classes/typedDelegation.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index e19521fa9b3..834c6dbbe83 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -803,28 +803,32 @@ public class FunctionCodegen extends GenerationStateAware { } public void genDelegate(FunctionDescriptor functionDescriptor, CallableMemberDescriptor overriddenDescriptor, StackValue field) { - JvmMethodSignature jvmMethodSignature = - state.getTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor); - genDelegate(functionDescriptor, overriddenDescriptor, field, jvmMethodSignature); + genDelegate(functionDescriptor, overriddenDescriptor, field, + typeMapper.mapSignature(functionDescriptor.getName(), functionDescriptor), + typeMapper.mapSignature(overriddenDescriptor.getName(), (FunctionDescriptor) overriddenDescriptor.getOriginal()) + ); } public void genDelegate( CallableMemberDescriptor functionDescriptor, CallableMemberDescriptor overriddenDescriptor, StackValue field, - JvmMethodSignature jvmMethodSignature + JvmMethodSignature jvmDelegateMethodSignature, + JvmMethodSignature jvmOverriddenMethodSignature ) { - Method method = jvmMethodSignature.getAsmMethod(); + Method overriddenMethod = jvmOverriddenMethodSignature.getAsmMethod(); + Method delegateMethod = jvmDelegateMethodSignature.getAsmMethod(); + int flags = ACC_PUBLIC | ACC_SYNTHETIC; // TODO. - final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null); + final MethodVisitor mv = v.newMethod(null, flags, delegateMethod.getName(), delegateMethod.getDescriptor(), null, null); if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { genStubCode(mv); } else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { mv.visitCode(); - Type[] argTypes = method.getArgumentTypes(); + Type[] argTypes = overriddenMethod.getArgumentTypes(); InstructionAdapter iv = new InstructionAdapter(mv); iv.load(0, OBJECT_TYPE); field.put(field.type, iv); @@ -832,10 +836,10 @@ public class FunctionCodegen extends GenerationStateAware { Type argType = argTypes[i]; iv.load(reg, argType); if (argType.getSort() == Type.OBJECT) { - StackValue.onStack(OBJECT_TYPE).put(method.getArgumentTypes()[i], iv); + StackValue.onStack(OBJECT_TYPE).put(overriddenMethod.getArgumentTypes()[i], iv); } else if (argType.getSort() == Type.ARRAY) { - StackValue.onStack(JAVA_ARRAY_GENERIC_TYPE).put(method.getArgumentTypes()[i], iv); + StackValue.onStack(JAVA_ARRAY_GENERIC_TYPE).put(overriddenMethod.getArgumentTypes()[i], iv); } //noinspection AssignmentToForLoopParameter @@ -846,12 +850,15 @@ public class FunctionCodegen extends GenerationStateAware { String internalName = state.getTypeMapper().mapType(classDescriptor).getInternalName(); if (classDescriptor.getKind() == ClassKind.TRAIT) { - iv.invokeinterface(internalName, method.getName(), method.getDescriptor()); + iv.invokeinterface(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor()); } else { - iv.invokevirtual(internalName, method.getName(), method.getDescriptor()); + iv.invokevirtual(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor()); } - iv.areturn(method.getReturnType()); + + StackValue.onStack(overriddenMethod.getReturnType()).put(delegateMethod.getReturnType(), iv); + + iv.areturn(delegateMethod.getReturnType()); endVisit(mv, "delegate method", descriptorToDeclaration(bindingContext, functionDescriptor)); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 4ebba0c4020..99750d462ad 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -342,13 +342,14 @@ public class PropertyCodegen extends GenerationStateAware { } public void genDelegate(PropertyDescriptor declaration, PropertyDescriptor overriddenDescriptor, StackValue field) { - JvmPropertyAccessorSignature jvmPropertyAccessorSignature = - typeMapper.mapGetterSignature(declaration, OwnerKind.IMPLEMENTATION); - functionCodegen.genDelegate(declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature()); + JvmMethodSignature getterSignature = + typeMapper.mapGetterSignature(declaration.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature(); + functionCodegen.genDelegate(declaration, overriddenDescriptor, field, getterSignature, getterSignature); if (declaration.isVar()) { - jvmPropertyAccessorSignature = typeMapper.mapSetterSignature(declaration, OwnerKind.IMPLEMENTATION); - functionCodegen.genDelegate(declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature()); + JvmMethodSignature setterSignature = + typeMapper.mapSetterSignature(declaration.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature(); + functionCodegen.genDelegate(declaration, overriddenDescriptor, field, setterSignature, setterSignature); } } } diff --git a/compiler/testData/codegen/classes/typedDelegation.kt b/compiler/testData/codegen/classes/typedDelegation.kt new file mode 100644 index 00000000000..df4867e1320 --- /dev/null +++ b/compiler/testData/codegen/classes/typedDelegation.kt @@ -0,0 +1,31 @@ +trait A { + var zzzValue : T + fun zzz() : T +} + +class Base : A { + override var zzzValue : T? = null + + override fun zzz() : T? = zzzValue +} + +class X : A by Base() + +fun box() : String { + (Base() as A).zzz() + + if (X().zzz() != null) { + return "Fail" + } + + val x = X() + x.zzzValue = "aa" + if (x.zzzValue != "aa") { + return "Fail 2"; + } + if (x.zzz() != "aa") { + return "Fail 3"; + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 49237a45573..104fb5f3fd9 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -110,6 +110,11 @@ public class ClassGenTest extends CodegenTestCase { blackBoxFile("classes/delegation4.kt"); } + public void testInheritanceAndDelegationTyped() throws Exception { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("classes/typedDelegation.kt"); + } + public void testDelegationMethodsWithArgs() throws Exception { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); blackBoxFile("classes/delegationMethodsWithArgs.kt");