Keep track of synthetic accessor parameter types
Accessor parameter types may be different from callee parameter types
in case of generic methods specialized by primitive types:
open class Base<T> {
protected fun foo(x: T) {}
}
// in different package
class Derived : Base<Long> {
inner class Inner {
fun bar() { foo(42L) }
}
}
Synthetic accessor for 'Base.foo' in 'Derived' has signature '(J)V'
(not '(Ljava.lang.Object;)V' or '(Ljava.lang.Long;)V'),
and should box its parameter.
Note that in Java the corresponding synthetic accessor has signature
'(Ljava.lang.Long;)V' with auto-boxing at call site.
#KT-20491 Fixed
This commit is contained in:
@@ -813,27 +813,37 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
);
|
||||
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) && !isNonDefaultInterfaceMember(functionDescriptor, state);
|
||||
int reg = hasDispatchReceiver ? 1 : 0;
|
||||
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
||||
|
||||
int accessorParam = (hasDispatchReceiver && !accessorIsConstructor) ? 1 : 0;
|
||||
int reg = hasDispatchReceiver ? 1 : 0;
|
||||
if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
|
||||
iv.anew(callableMethod.getOwner());
|
||||
iv.dup();
|
||||
reg = 0;
|
||||
accessorParam = 0;
|
||||
}
|
||||
else if (accessorIsConstructor || (accessorDescriptor != null && KotlinTypeMapper.isAccessor(accessorDescriptor) && hasDispatchReceiver)) {
|
||||
else if (KotlinTypeMapper.isAccessor(accessorDescriptor) && (hasDispatchReceiver || accessorIsConstructor)) {
|
||||
if (!CodegenUtilKt.isJvmStaticInObjectOrClass(functionDescriptor)) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
for (Type argType : callableMethod.getParameterTypes()) {
|
||||
if (AsmTypes.DEFAULT_CONSTRUCTOR_MARKER.equals(argType)) {
|
||||
Type[] calleeParameterTypes = callableMethod.getParameterTypes();
|
||||
Type[] accessorParameterTypes = accessorDescriptor != null
|
||||
? typeMapper.mapToCallableMethod(accessorDescriptor, false).getParameterTypes()
|
||||
: calleeParameterTypes;
|
||||
for (Type calleeArgType: calleeParameterTypes) {
|
||||
if (AsmTypes.DEFAULT_CONSTRUCTOR_MARKER.equals(calleeArgType)) {
|
||||
iv.aconst(null);
|
||||
}
|
||||
else {
|
||||
iv.load(reg, argType);
|
||||
reg += argType.getSize();
|
||||
Type accessorParameterType = accessorParameterTypes[accessorParam];
|
||||
iv.load(reg, accessorParameterType);
|
||||
StackValue.coerce(accessorParameterType, calleeArgType, iv);
|
||||
reg += accessorParameterType.getSize();
|
||||
}
|
||||
accessorParam++;
|
||||
}
|
||||
|
||||
callableMethod.genInvokeInstruction(iv);
|
||||
|
||||
@@ -831,11 +831,11 @@ public class KotlinTypeMapper {
|
||||
JvmCodegenUtil.isJvm8InterfaceWithDefaults(ownerForDefault, isJvm8Target, isJvm8TargetWithDefaults);
|
||||
}
|
||||
|
||||
public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
|
||||
public static boolean isAccessor(@Nullable CallableMemberDescriptor descriptor) {
|
||||
return descriptor instanceof AccessorForCallableDescriptor<?>;
|
||||
}
|
||||
|
||||
public static boolean isStaticAccessor(@NotNull CallableMemberDescriptor descriptor) {
|
||||
public static boolean isStaticAccessor(@Nullable CallableMemberDescriptor descriptor) {
|
||||
if (descriptor instanceof AccessorForConstructorDescriptor) return false;
|
||||
return isAccessor(descriptor);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user