KT-2987 java.lang.AbstractMethodError/java.lang.NoSuchMethodError for delegated class by parameterized parent
#KT-2987 Fixed
This commit is contained in:
committed by
Alexander Udalov
parent
c843d23416
commit
edb8797fa6
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user