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);
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
fun box(): String {
|
||||
A.Nested().nestedA()
|
||||
A.Nested().Inner().innerA()
|
||||
A.companionA()
|
||||
return "OK"
|
||||
}
|
||||
|
||||
class A<T> private constructor(val x: T, val y: Int = 0) {
|
||||
class Nested {
|
||||
fun nestedA() = A<Long>(1L)
|
||||
|
||||
inner class Inner {
|
||||
fun innerA() = A<Long>(1L)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun companionA() = A<Long>(1L)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// FILE: test.kt
|
||||
import b.B
|
||||
|
||||
fun box() =
|
||||
B().getOK()
|
||||
|
||||
// FILE: a.kt
|
||||
package a
|
||||
|
||||
open class A<T> {
|
||||
protected fun getO(x: T) = "O"
|
||||
protected fun getK(x: T) = "K"
|
||||
}
|
||||
|
||||
// FILE: b.kt
|
||||
package b
|
||||
|
||||
import a.A
|
||||
|
||||
class B : A<Long>() {
|
||||
inner class Inner {
|
||||
fun innerGetO() = getO(0L)
|
||||
}
|
||||
|
||||
fun lambdaGetK() = { -> getK(0L) }
|
||||
|
||||
fun getOK() =
|
||||
Inner().innerGetO() + lambdaGetK().invoke()
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// FILE: test.kt
|
||||
import b.B
|
||||
|
||||
fun box() =
|
||||
B().getOK()
|
||||
|
||||
// FILE: a.kt
|
||||
package a
|
||||
|
||||
open class A<T> {
|
||||
protected fun getO(x: T, z: String = "") = "O" + z
|
||||
protected fun getK(x: T, z: String = "") = "K" + z
|
||||
}
|
||||
|
||||
// FILE: b.kt
|
||||
package b
|
||||
|
||||
import a.A
|
||||
|
||||
class B : A<Long>() {
|
||||
inner class Inner {
|
||||
fun innerGetO() = getO(0L)
|
||||
}
|
||||
|
||||
fun lambdaGetK() = { -> getK(0L) }
|
||||
|
||||
fun getOK() =
|
||||
Inner().innerGetO() + lambdaGetK().invoke()
|
||||
}
|
||||
+18
@@ -18967,6 +18967,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SyntheticAccessors extends AbstractIrBlackBoxCodegenTest {
|
||||
@TestMetadata("accessorForGenericConstructor.kt")
|
||||
public void testAccessorForGenericConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForGenericMethod.kt")
|
||||
public void testAccessorForGenericMethod() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericMethod.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForGenericMethodWithDefaults.kt")
|
||||
public void testAccessorForGenericMethodWithDefaults() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericMethodWithDefaults.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForProtected.kt")
|
||||
public void testAccessorForProtected() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForProtected.kt");
|
||||
|
||||
@@ -18967,6 +18967,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SyntheticAccessors extends AbstractBlackBoxCodegenTest {
|
||||
@TestMetadata("accessorForGenericConstructor.kt")
|
||||
public void testAccessorForGenericConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForGenericMethod.kt")
|
||||
public void testAccessorForGenericMethod() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericMethod.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForGenericMethodWithDefaults.kt")
|
||||
public void testAccessorForGenericMethodWithDefaults() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericMethodWithDefaults.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForProtected.kt")
|
||||
public void testAccessorForProtected() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForProtected.kt");
|
||||
|
||||
@@ -18967,6 +18967,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SyntheticAccessors extends AbstractLightAnalysisModeTest {
|
||||
@TestMetadata("accessorForGenericConstructor.kt")
|
||||
public void testAccessorForGenericConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForGenericMethod.kt")
|
||||
public void testAccessorForGenericMethod() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericMethod.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForGenericMethodWithDefaults.kt")
|
||||
public void testAccessorForGenericMethodWithDefaults() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericMethodWithDefaults.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForProtected.kt")
|
||||
public void testAccessorForProtected() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForProtected.kt");
|
||||
|
||||
+18
@@ -22849,6 +22849,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SyntheticAccessors extends AbstractJsCodegenBoxTest {
|
||||
@TestMetadata("accessorForGenericConstructor.kt")
|
||||
public void testAccessorForGenericConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForGenericMethod.kt")
|
||||
public void testAccessorForGenericMethod() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericMethod.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForGenericMethodWithDefaults.kt")
|
||||
public void testAccessorForGenericMethodWithDefaults() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForGenericMethodWithDefaults.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorForProtected.kt")
|
||||
public void testAccessorForProtected() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/syntheticAccessors/accessorForProtected.kt");
|
||||
|
||||
Reference in New Issue
Block a user