Fix for KT-2789: NoSuchMethodError when calling trait function with default arguments that returns generic type, KT-9428 Abstract method with one parameter and one default parameter produces NoSuchMethodError, KT-9924 NoSuchMethod when replacing generic with specific type

#KT-2789 Fixed
 #KT-9428 Fixed
 #KT-9924 Fixed
This commit is contained in:
Michael Bogdanov
2015-11-12 13:04:56 +03:00
parent 3f995935d3
commit 7e8e4e9e1b
6 changed files with 116 additions and 18 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
@@ -31,7 +30,7 @@ import org.jetbrains.org.objectweb.asm.util.Printer
public class CallableMethod(
override val owner: Type,
private val defaultImplOwner: Type?,
private val defaultImplParam: Type?,
private val defaultMethodDesc: String,
private val signature: JvmMethodSignature,
private val invokeOpcode: Int,
override val dispatchReceiverType: Type?,
@@ -56,24 +55,21 @@ public class CallableMethod(
}
public fun genInvokeDefaultInstruction(v: InstructionAdapter) {
if (defaultImplOwner == null || defaultImplParam == null) {
if (defaultImplOwner == null) {
throw IllegalStateException()
}
val method = getAsmMethod()
val desc = JetTypeMapper.getDefaultDescriptor(
method,
if (invokeOpcode == INVOKESTATIC) null else defaultImplParam.getDescriptor(),
extensionReceiverType != null
)
if ("<init>".equals(method.getName())) {
v.aconst(null)
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.getInternalName(), "<init>", desc, false)
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.getInternalName(), "<init>", defaultMethodDesc, false)
}
else {
v.visitMethodInsn(INVOKESTATIC, defaultImplOwner.getInternalName(),
method.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, desc, false)
method.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, false)
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
}
}
@@ -734,7 +734,8 @@ public class JetTypeMapper {
if (descriptor instanceof ConstructorDescriptor) {
JvmMethodSignature method = mapSignature(descriptor);
Type owner = mapClass(((ConstructorDescriptor) descriptor).getContainingDeclaration());
return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
String defaultImplDesc = mapDefaultMethod(descriptor, OwnerKind.IMPLEMENTATION).getDescriptor();
return new CallableMethod(owner, owner, defaultImplDesc, method, INVOKESPECIAL, null, null, null);
}
DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
@@ -744,7 +745,7 @@ public class JetTypeMapper {
JvmMethodSignature signature;
Type owner;
Type ownerForDefaultImpl;
Type ownerForDefaultParam;
FunctionDescriptor baseMethodDescriptor;
int invokeOpcode;
Type thisClass;
@@ -759,9 +760,9 @@ public class JetTypeMapper {
boolean isInterface = currentIsInterface && originalIsInterface;
ClassDescriptor ownerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
ownerForDefaultParam = mapClass(ownerForDefault);
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : ownerForDefaultParam;
baseMethodDescriptor = findBaseDeclaration(functionDescriptor).getOriginal();
ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE)) {
thisClass = mapClass(currentOwner);
@@ -810,8 +811,8 @@ public class JetTypeMapper {
else {
signature = mapSignature(functionDescriptor.getOriginal());
owner = mapOwner(functionDescriptor);
ownerForDefaultParam = owner;
ownerForDefaultImpl = owner;
baseMethodDescriptor = functionDescriptor;
if (functionParent instanceof PackageFragmentDescriptor) {
invokeOpcode = INVOKESTATIC;
thisClass = null;
@@ -836,8 +837,11 @@ public class JetTypeMapper {
else {
receiverParameterType = null;
}
String defaultImplDesc = mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)).getDescriptor();
return new CallableMethod(
owner, ownerForDefaultImpl, ownerForDefaultParam, signature, invokeOpcode,
owner, ownerForDefaultImpl, defaultImplDesc, signature, invokeOpcode,
thisClass, receiverParameterType, calleeType);
}
@@ -918,6 +922,18 @@ public class JetTypeMapper {
}
}
@NotNull
private static OwnerKind getKindForDefaultImplCall(@NotNull FunctionDescriptor baseMethodDescriptor) {
DeclarationDescriptor containingDeclaration = baseMethodDescriptor.getContainingDeclaration();
if (containingDeclaration instanceof PackageFragmentDescriptor) {
return OwnerKind.PACKAGE;
}
else if (isInterface(containingDeclaration)) {
return OwnerKind.DEFAULT_IMPLS;
}
return OwnerKind.IMPLEMENTATION;
}
@NotNull
public static String mapDefaultFieldName(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegated) {
String name;
@@ -1047,7 +1063,7 @@ public class JetTypeMapper {
}
@NotNull
public static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
private static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
String descriptor = method.getDescriptor();
int argumentsCount = Type.getArgumentTypes(descriptor).length;
if (isExtension) {