[parcelize] Fix codegen for generic classes

Replace type arguments with star projection in static methods
Fix IR function generation

^KT-42652  Fixed
This commit is contained in:
Andrey Zinovyev
2021-02-04 15:11:51 +03:00
committed by GitHub
parent ca02573d1e
commit 95140f35f8
10 changed files with 204 additions and 3 deletions
@@ -168,7 +168,8 @@ fun IrClass.addFunction(
this.origin = origin
}.apply {
if (!isStatic) {
dispatchReceiverParameter = parentAsClass.thisReceiver!!.copyTo(this)
val thisReceiver = parentAsClass.thisReceiver!!
dispatchReceiverParameter = thisReceiver.copyTo(this, type = thisReceiver.type)
}
}
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
@@ -220,7 +221,7 @@ open class ParcelizeCodegenExtension : ParcelizeExtensionBase, ExpressionCodegen
createMethod(
creatorClass, CREATE_FROM_PARCEL, Modality.FINAL,
parcelableClass.defaultType, "in" to parcelClassType
parcelableClass.defaultType.replaceArgumentsWithStarProjections(), "in" to parcelClassType
).write(codegen, overriddenFunction) {
if (parcelerObject != null) {
val (companionAsmType, companionFieldName) = getCompanionClassType(containerAsmType, parcelerObject)
@@ -368,7 +369,7 @@ open class ParcelizeCodegenExtension : ParcelizeExtensionBase, ExpressionCodegen
createMethod(
creatorClass, NEW_ARRAY, Modality.FINAL,
builtIns.getArrayType(Variance.INVARIANT, parcelableClass.defaultType),
builtIns.getArrayType(Variance.INVARIANT, parcelableClass.defaultType.replaceArgumentsWithStarProjections()),
"size" to builtIns.intType
).write(codegen, overriddenFunction) {
if (parcelerObject != null) {
@@ -0,0 +1,27 @@
// WITH_RUNTIME
@file:JvmName("TestKt")
package test
import kotlinx.parcelize.*
import android.os.Parcel
import android.os.Parcelable
@Parcelize
data class Foo(val value: Int) : Parcelable
@Parcelize
data class Box<T : Parcelable>(val box: T) : Parcelable
fun box() = parcelTest { parcel ->
val foo = Foo(42)
val box = Box(foo)
box.writeToParcel(parcel, 0)
val bytes = parcel.marshall()
parcel.unmarshall(bytes, 0, bytes.size)
parcel.setDataPosition(0)
val boxLoaded = readFromParcel<Box<Foo>>(parcel)
assert(box == boxLoaded)
}
@@ -0,0 +1,72 @@
public final class Box$Creator : java/lang/Object, android/os/Parcelable$Creator {
public void <init>()
public final Box createFromParcel(android.os.Parcel parcel) {
LABEL (L0)
ALOAD (1)
LDC (parcel)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
NEW
DUP
ALOAD (1)
LDC (LBox;)
INVOKEVIRTUAL (java/lang/Class, getClassLoader, ()Ljava/lang/ClassLoader;)
INVOKEVIRTUAL (android/os/Parcel, readParcelable, (Ljava/lang/ClassLoader;)Landroid/os/Parcelable;)
INVOKESPECIAL (Box, <init>, (Landroid/os/Parcelable;)V)
ARETURN
LABEL (L1)
}
public java.lang.Object createFromParcel(android.os.Parcel source) {
LABEL (L0)
ALOAD (0)
ALOAD (1)
INVOKEVIRTUAL (Box$Creator, createFromParcel, (Landroid/os/Parcel;)LBox;)
ARETURN
LABEL (L1)
}
public final Box[] newArray(int size)
public java.lang.Object[] newArray(int size)
}
public final class Box : java/lang/Object, android/os/Parcelable {
public final static android.os.Parcelable$Creator CREATOR
private final android.os.Parcelable box
static void <clinit>()
public void <init>(android.os.Parcelable box)
public final android.os.Parcelable component1()
public final Box copy(android.os.Parcelable box)
public static Box copy$default(Box p0, android.os.Parcelable p1, int p2, java.lang.Object p3)
public int describeContents()
public boolean equals(java.lang.Object other)
public final android.os.Parcelable getBox()
public int hashCode()
public java.lang.String toString()
public void writeToParcel(android.os.Parcel out, int flags) {
LABEL (L0)
ALOAD (1)
LDC (out)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
ALOAD (1)
ALOAD (0)
GETFIELD (box, Landroid/os/Parcelable;)
ILOAD (2)
INVOKEVIRTUAL (android/os/Parcel, writeParcelable, (Landroid/os/Parcelable;I)V)
RETURN
LABEL (L1)
}
}
@@ -0,0 +1,8 @@
// CURIOUS_ABOUT writeToParcel, createFromParcel
// WITH_RUNTIME
import kotlinx.parcelize.*
import android.os.Parcelable
@Parcelize
data class Box<T : Parcelable>(val box: T) : Parcelable
@@ -0,0 +1,72 @@
public final class Box$Creator : java/lang/Object, android/os/Parcelable$Creator {
public void <init>()
public final Box createFromParcel(android.os.Parcel in) {
LABEL (L0)
ALOAD (1)
LDC (in)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
NEW
DUP
ALOAD (1)
LDC (LBox;)
INVOKEVIRTUAL (java/lang/Class, getClassLoader, ()Ljava/lang/ClassLoader;)
INVOKEVIRTUAL (android/os/Parcel, readParcelable, (Ljava/lang/ClassLoader;)Landroid/os/Parcelable;)
INVOKESPECIAL (Box, <init>, (Landroid/os/Parcelable;)V)
ARETURN
LABEL (L1)
}
public java.lang.Object createFromParcel(android.os.Parcel p0) {
LABEL (L0)
LINENUMBER (8)
ALOAD (0)
ALOAD (1)
INVOKEVIRTUAL (Box$Creator, createFromParcel, (Landroid/os/Parcel;)LBox;)
ARETURN
}
public final Box[] newArray(int size)
public java.lang.Object[] newArray(int p0)
}
public final class Box : java/lang/Object, android/os/Parcelable {
public final static android.os.Parcelable$Creator CREATOR
private final android.os.Parcelable box
static void <clinit>()
public void <init>(android.os.Parcelable box)
public final android.os.Parcelable component1()
public final Box copy(android.os.Parcelable box)
public static Box copy$default(Box p0, android.os.Parcelable p1, int p2, java.lang.Object p3)
public int describeContents()
public boolean equals(java.lang.Object p0)
public final android.os.Parcelable getBox()
public int hashCode()
public java.lang.String toString()
public void writeToParcel(android.os.Parcel parcel, int flags) {
LABEL (L0)
ALOAD (1)
LDC (parcel)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
ALOAD (1)
ALOAD (0)
GETFIELD (box, Landroid/os/Parcelable;)
ILOAD (2)
INVOKEVIRTUAL (android/os/Parcel, writeParcelable, (Landroid/os/Parcelable;I)V)
RETURN
LABEL (L1)
}
}
@@ -120,6 +120,11 @@ public class ParcelizeBoxTestGenerated extends AbstractParcelizeBoxTest {
runTest("plugins/parcelize/parcelize-compiler/testData/box/functions.kt");
}
@TestMetadata("generics.kt")
public void testGenerics() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/box/generics.kt");
}
@TestMetadata("intArray.kt")
public void testIntArray() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/box/intArray.kt");
@@ -70,6 +70,11 @@ public class ParcelizeBytecodeListingTestGenerated extends AbstractParcelizeByte
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/efficientParcelable.kt");
}
@TestMetadata("generics.kt")
public void testGenerics() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/generics.kt");
}
@TestMetadata("IBinderIInterface.kt")
public void testIBinderIInterface() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/IBinderIInterface.kt");
@@ -120,6 +120,11 @@ public class ParcelizeIrBoxTestGenerated extends AbstractParcelizeIrBoxTest {
runTest("plugins/parcelize/parcelize-compiler/testData/box/functions.kt");
}
@TestMetadata("generics.kt")
public void testGenerics() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/box/generics.kt");
}
@TestMetadata("intArray.kt")
public void testIntArray() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/box/intArray.kt");
@@ -70,6 +70,11 @@ public class ParcelizeIrBytecodeListingTestGenerated extends AbstractParcelizeIr
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/efficientParcelable.kt");
}
@TestMetadata("generics.kt")
public void testGenerics() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/generics.kt");
}
@TestMetadata("IBinderIInterface.kt")
public void testIBinderIInterface() throws Exception {
runTest("plugins/parcelize/parcelize-compiler/testData/codegen/IBinderIInterface.kt");