KT-2987 java.lang.AbstractMethodError/java.lang.NoSuchMethodError for delegated class by parameterized parent

#KT-2987 Fixed
This commit is contained in:
Sergey Mashkov
2012-10-24 18:29:31 +04:00
committed by Alexander Udalov
parent c843d23416
commit edb8797fa6
4 changed files with 61 additions and 17 deletions
@@ -803,28 +803,32 @@ public class FunctionCodegen extends GenerationStateAware {
} }
public void genDelegate(FunctionDescriptor functionDescriptor, CallableMemberDescriptor overriddenDescriptor, StackValue field) { public void genDelegate(FunctionDescriptor functionDescriptor, CallableMemberDescriptor overriddenDescriptor, StackValue field) {
JvmMethodSignature jvmMethodSignature = genDelegate(functionDescriptor, overriddenDescriptor, field,
state.getTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor); typeMapper.mapSignature(functionDescriptor.getName(), functionDescriptor),
genDelegate(functionDescriptor, overriddenDescriptor, field, jvmMethodSignature); typeMapper.mapSignature(overriddenDescriptor.getName(), (FunctionDescriptor) overriddenDescriptor.getOriginal())
);
} }
public void genDelegate( public void genDelegate(
CallableMemberDescriptor functionDescriptor, CallableMemberDescriptor functionDescriptor,
CallableMemberDescriptor overriddenDescriptor, CallableMemberDescriptor overriddenDescriptor,
StackValue field, 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. 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) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
genStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
Type[] argTypes = method.getArgumentTypes(); Type[] argTypes = overriddenMethod.getArgumentTypes();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, OBJECT_TYPE); iv.load(0, OBJECT_TYPE);
field.put(field.type, iv); field.put(field.type, iv);
@@ -832,10 +836,10 @@ public class FunctionCodegen extends GenerationStateAware {
Type argType = argTypes[i]; Type argType = argTypes[i];
iv.load(reg, argType); iv.load(reg, argType);
if (argType.getSort() == Type.OBJECT) { 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) { 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 //noinspection AssignmentToForLoopParameter
@@ -846,12 +850,15 @@ public class FunctionCodegen extends GenerationStateAware {
String internalName = String internalName =
state.getTypeMapper().mapType(classDescriptor).getInternalName(); state.getTypeMapper().mapType(classDescriptor).getInternalName();
if (classDescriptor.getKind() == ClassKind.TRAIT) { if (classDescriptor.getKind() == ClassKind.TRAIT) {
iv.invokeinterface(internalName, method.getName(), method.getDescriptor()); iv.invokeinterface(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor());
} }
else { 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)); endVisit(mv, "delegate method", descriptorToDeclaration(bindingContext, functionDescriptor));
} }
} }
@@ -342,13 +342,14 @@ public class PropertyCodegen extends GenerationStateAware {
} }
public void genDelegate(PropertyDescriptor declaration, PropertyDescriptor overriddenDescriptor, StackValue field) { public void genDelegate(PropertyDescriptor declaration, PropertyDescriptor overriddenDescriptor, StackValue field) {
JvmPropertyAccessorSignature jvmPropertyAccessorSignature = JvmMethodSignature getterSignature =
typeMapper.mapGetterSignature(declaration, OwnerKind.IMPLEMENTATION); typeMapper.mapGetterSignature(declaration.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature();
functionCodegen.genDelegate(declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature()); functionCodegen.genDelegate(declaration, overriddenDescriptor, field, getterSignature, getterSignature);
if (declaration.isVar()) { if (declaration.isVar()) {
jvmPropertyAccessorSignature = typeMapper.mapSetterSignature(declaration, OwnerKind.IMPLEMENTATION); JvmMethodSignature setterSignature =
functionCodegen.genDelegate(declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature()); typeMapper.mapSetterSignature(declaration.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature();
functionCodegen.genDelegate(declaration, overriddenDescriptor, field, setterSignature, setterSignature);
} }
} }
} }
@@ -0,0 +1,31 @@
trait A<T> {
var zzzValue : T
fun zzz() : T
}
class Base<T> : A<T?> {
override var zzzValue : T? = null
override fun zzz() : T? = zzzValue
}
class X : A<String?> by Base<String?>()
fun box() : String {
(Base<String?>() as A<String?>).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"
}
@@ -110,6 +110,11 @@ public class ClassGenTest extends CodegenTestCase {
blackBoxFile("classes/delegation4.kt"); blackBoxFile("classes/delegation4.kt");
} }
public void testInheritanceAndDelegationTyped() throws Exception {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
blackBoxFile("classes/typedDelegation.kt");
}
public void testDelegationMethodsWithArgs() throws Exception { public void testDelegationMethodsWithArgs() throws Exception {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
blackBoxFile("classes/delegationMethodsWithArgs.kt"); blackBoxFile("classes/delegationMethodsWithArgs.kt");