Fix IR validation warnings in serialization plugin

- Insert patchDeclarationParents after whole processing
- Copy IR nodes to avoid duplications
- Insert correct type for getter during serialization of properties from parent class
- Do not use irThrowIse because it is broken somewhere in Native backend
This commit is contained in:
Leonid Startsev
2019-08-30 13:26:38 +03:00
parent d3f1cf1cdd
commit 4e516d7c94
5 changed files with 64 additions and 66 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -423,12 +424,14 @@ interface IrBuilderExtension {
original.valueParameters.associate { it.descriptor to it.defaultValue?.expression } original.valueParameters.associate { it.descriptor to it.defaultValue?.expression }
return fun(f: IrField): IrExpression? { return fun(f: IrField): IrExpression? {
val i = f.initializer?.expression ?: return null val i = f.initializer?.expression ?: return null
return if (i is IrGetValueImpl && i.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) { val irExpression =
// this is a primary constructor property, use corresponding default of value parameter if (i is IrGetValueImpl && i.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) {
defaultsMap.getValue(i.descriptor as ParameterDescriptor) // this is a primary constructor property, use corresponding default of value parameter
} else { defaultsMap.getValue(i.descriptor as ParameterDescriptor)
i } else {
} i
}
return irExpression?.deepCopyWithVariables()
} }
} }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
@@ -40,8 +41,10 @@ class SerializableCompanionIrGenerator(
) { ) {
val companionDescriptor = irClass.descriptor val companionDescriptor = irClass.descriptor
val serializableClass = getSerializableClassDescriptorByCompanion(companionDescriptor) ?: return val serializableClass = getSerializableClassDescriptorByCompanion(companionDescriptor) ?: return
if (serializableClass.shouldHaveGeneratedMethodsInCompanion) if (serializableClass.shouldHaveGeneratedMethodsInCompanion) {
SerializableCompanionIrGenerator(irClass, context, bindingContext).generate() SerializableCompanionIrGenerator(irClass, context, bindingContext).generate()
irClass.patchDeclarationParents(irClass.parent)
}
} }
} }
@@ -1,19 +1,23 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.CompilationException import org.jetbrains.kotlin.codegen.CompilationException
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
@@ -99,22 +103,10 @@ class SerializableIrGenerator(
irClass.declarations.asSequence() irClass.declarations.asSequence()
.filterIsInstance<IrAnonymousInitializer>() .filterIsInstance<IrAnonymousInitializer>()
.forEach { initializer -> .forEach { initializer ->
initializer.body.statements.forEach { +it.deepCopyWithSymbols(initialParent = ctor) } initializer.body.deepCopyWithVariables().statements.forEach { +it }
} }
} }
// todo: this is copypaste from DeepCopyIrWithSymbols.kt,
// remove after KT-18563 is fixed and bootstrap updated.
private inline fun <reified T : IrElement> T.deepCopyWithSymbols(
initialParent: IrDeclarationParent? = null,
descriptorRemapper: DescriptorsRemapper = DescriptorsRemapper.Default
): T {
val symbolRemapper = DeepCopySymbolRemapper(descriptorRemapper)
acceptVoid(symbolRemapper)
val typeRemapper = DeepCopyTypeRemapper(symbolRemapper)
return transform(DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper), null).patchDeclarationParents(initialParent) as T
}
private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: ClassDescriptor) { private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: ClassDescriptor) {
val suitableCtor = superClass.constructors.singleOrNull { it.valueParameters.size == 0 } val suitableCtor = superClass.constructors.singleOrNull { it.valueParameters.size == 0 }
?: throw IllegalArgumentException("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor") ?: throw IllegalArgumentException("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor")
@@ -165,8 +157,10 @@ class SerializableIrGenerator(
) { ) {
val serializableClass = irClass.descriptor val serializableClass = irClass.descriptor
if (serializableClass.isInternalSerializable) if (serializableClass.isInternalSerializable) {
SerializableIrGenerator(irClass, context, bindingContext).generate() SerializableIrGenerator(irClass, context, bindingContext).generate()
irClass.patchDeclarationParents(irClass.parent)
}
else if (serializableClass.hasSerializableAnnotationWithoutArgs && !serializableClass.hasCompanionObjectAsSerializer) { else if (serializableClass.hasSerializableAnnotationWithoutArgs && !serializableClass.hasCompanionObjectAsSerializer) {
throw CompilationException( throw CompilationException(
"@Serializable annotation on $serializableClass would be ignored because it is impossible to serialize it automatically. " + "@Serializable annotation on $serializableClass would be ignored because it is impossible to serialize it automatically. " +
@@ -6,6 +6,7 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.backend.common.lower.irThrow
@@ -101,14 +102,14 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
// add property annotations // add property annotations
copySerialInfoAnnotationsToDescriptor( copySerialInfoAnnotationsToDescriptor(
classProp.irField.correspondingProperty?.annotations.orEmpty(), classProp.irField.correspondingProperty?.annotations.orEmpty(),
irGet(localDesc), localDesc,
serialDescImplClass.referenceMethod(CallingConventions.addAnnotation) serialDescImplClass.referenceMethod(CallingConventions.addAnnotation)
) )
} }
// add class annotations // add class annotations
copySerialInfoAnnotationsToDescriptor( copySerialInfoAnnotationsToDescriptor(
serializableIrClass.annotations, serializableIrClass.annotations,
irGet(localDesc), localDesc,
serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation) serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation)
) )
@@ -129,12 +130,12 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
private fun IrBlockBodyBuilder.copySerialInfoAnnotationsToDescriptor( private fun IrBlockBodyBuilder.copySerialInfoAnnotationsToDescriptor(
annotations: List<IrConstructorCall>, annotations: List<IrConstructorCall>,
receiver: IrExpression, receiver: IrVariable,
method: IrFunctionSymbol method: IrFunctionSymbol
) { ) {
annotations.forEach { annotationCall -> annotations.forEach { annotationCall ->
if ((annotationCall.descriptor as? ClassConstructorDescriptor)?.constructedClass?.isSerialInfoAnnotation == true) if ((annotationCall.descriptor as? ClassConstructorDescriptor)?.constructedClass?.isSerialInfoAnnotation == true)
+irInvoke(receiver, method, annotationCall) +irInvoke(irGet(receiver), method, annotationCall.deepCopyWithVariables())
} }
} }
@@ -216,8 +217,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
val localOutput = irTemporary(call, "output") val localOutput = irTemporary(call, "output")
fun SerializableProperty.irGet(): IrGetField { fun SerializableProperty.irGet(): IrGetField {
val ownerType = (descriptor.containingDeclaration as? ClassDescriptor)?.defaultType?.toIrType() ?: val ownerType = objectToSerialize.symbol.owner.type
throw IllegalStateException("Serializable property must be contained in class")
return irGetField( return irGetField(
irGet( irGet(
type = ownerType, type = ownerType,
@@ -303,6 +303,10 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
} }
override fun generateLoad(function: FunctionDescriptor) = irClass.contributeFunction(function, fromStubs = true) { loadFunc -> override fun generateLoad(function: FunctionDescriptor) = irClass.contributeFunction(function, fromStubs = true) { loadFunc ->
if (serializableDescriptor.modality == Modality.ABSTRACT || serializableDescriptor.modality == Modality.SEALED) {
return@contributeFunction
}
fun irThis(): IrExpression = fun irThis(): IrExpression =
IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol) IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol)
@@ -351,7 +355,6 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
+irSetVar(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get())) +irSetVar(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get()))
+irWhen { +irWhen {
// if index == -2 (READ_ALL) todo... // if index == -2 (READ_ALL) todo...
+IrBranchImpl(irEquals(indexVar.get(), irInt(-2)), irThrowIse()) // TODO throw proper exception
// if index == -1 (READ_DONE) break loop // if index == -1 (READ_DONE) break loop
+IrBranchImpl(irEquals(indexVar.get(), irInt(-1)), irSetVar(flagVar.symbol, irBoolean(false))) +IrBranchImpl(irEquals(indexVar.get(), irInt(-1)), irSetVar(flagVar.symbol, irBoolean(false)))
@@ -432,12 +435,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
compilerContext.externalSymbols.referenceConstructor(serializableDescriptor.unsubstitutedPrimaryConstructor!!) compilerContext.externalSymbols.referenceConstructor(serializableDescriptor.unsubstitutedPrimaryConstructor!!)
} }
// todo: throw UnsupportedOperationException when feature branch with `open SerializerGenerator` (enums) will be merged +irReturn(irInvoke(null, ctor, typeArgs, args))
if (serializableDescriptor.modality != Modality.ABSTRACT && serializableDescriptor.modality != Modality.SEALED) {
+irReturn(irInvoke(null, ctor, typeArgs, args))
} else {
+irThrowIse() // TODO throw proper exception
}
} }
companion object { companion object {
@@ -446,8 +444,10 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
context: BackendContext, context: BackendContext,
bindingContext: BindingContext bindingContext: BindingContext
) { ) {
if (getSerializableClassDescriptorBySerializer(irClass.descriptor) != null) if (getSerializableClassDescriptorBySerializer(irClass.descriptor) != null) {
SerializerIrGenerator(irClass, context, bindingContext).generate() SerializerIrGenerator(irClass, context, bindingContext).generate()
irClass.patchDeclarationParents(irClass.parent)
}
} }
} }
} }
@@ -40,7 +40,8 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
LINENUMBER (12) LINENUMBER (12)
ICONST_1 ICONST_1
ANEWARRAY ANEWARRAY
DUP ASTORE (1)
ALOAD (1)
ICONST_0 ICONST_0
NEW NEW
DUP DUP
@@ -48,6 +49,7 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
CHECKCAST CHECKCAST
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V) INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
AASTORE AASTORE
ALOAD (1)
ARETURN ARETURN
LABEL (L1) LABEL (L1)
} }
@@ -86,13 +88,10 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
ILOAD (4) ILOAD (4)
TABLESWITCH TABLESWITCH
LABEL (L4) LABEL (L4)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, throwNpe, ()V)
GOTO (L5)
LABEL (L6)
ICONST_0 ICONST_0
ISTORE (3) ISTORE (3)
GOTO (L5) GOTO (L5)
LABEL (L7) LABEL (L6)
ALOAD (7) ALOAD (7)
ALOAD (2) ALOAD (2)
ICONST_0 ICONST_0
@@ -111,7 +110,7 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
IOR IOR
ISTORE (5) ISTORE (5)
GOTO (L5) GOTO (L5)
LABEL (L8) LABEL (L7)
NEW NEW
DUP DUP
ILOAD (4) ILOAD (4)
@@ -124,7 +123,7 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
LABEL (L3) LABEL (L3)
ALOAD (7) ALOAD (7)
ALOAD (2) ALOAD (2)
LABEL (L9) LABEL (L8)
LINENUMBER (12) LINENUMBER (12)
INVOKEINTERFACE (kotlinx/serialization/CompositeDecoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) INVOKEINTERFACE (kotlinx/serialization/CompositeDecoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V)
NEW NEW
@@ -136,7 +135,7 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
CHECKCAST CHECKCAST
INVOKESPECIAL (ListOfUsers, <init>, (ILjava/util/List;Lkotlinx/serialization/SerializationConstructorMarker;)V) INVOKESPECIAL (ListOfUsers, <init>, (ILjava/util/List;Lkotlinx/serialization/SerializationConstructorMarker;)V)
ARETURN ARETURN
LABEL (L10) LABEL (L9)
} }
public java.lang.Object deserialize(kotlinx.serialization.Decoder decoder) { public java.lang.Object deserialize(kotlinx.serialization.Decoder decoder) {
@@ -330,11 +329,13 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
LINENUMBER (9) LINENUMBER (9)
ICONST_1 ICONST_1
ANEWARRAY ANEWARRAY
DUP ASTORE (1)
ALOAD (1)
ICONST_0 ICONST_0
GETSTATIC (INSTANCE, LUser$$serializer;) GETSTATIC (INSTANCE, LUser$$serializer;)
CHECKCAST CHECKCAST
AASTORE AASTORE
ALOAD (1)
ARETURN ARETURN
LABEL (L1) LABEL (L1)
} }
@@ -373,13 +374,10 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
ILOAD (4) ILOAD (4)
TABLESWITCH TABLESWITCH
LABEL (L4) LABEL (L4)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, throwNpe, ()V)
GOTO (L5)
LABEL (L6)
ICONST_0 ICONST_0
ISTORE (3) ISTORE (3)
GOTO (L5) GOTO (L5)
LABEL (L7) LABEL (L6)
ALOAD (7) ALOAD (7)
ALOAD (2) ALOAD (2)
ICONST_0 ICONST_0
@@ -394,7 +392,7 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
IOR IOR
ISTORE (5) ISTORE (5)
GOTO (L5) GOTO (L5)
LABEL (L8) LABEL (L7)
NEW NEW
DUP DUP
ILOAD (4) ILOAD (4)
@@ -407,7 +405,7 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
LABEL (L3) LABEL (L3)
ALOAD (7) ALOAD (7)
ALOAD (2) ALOAD (2)
LABEL (L9) LABEL (L8)
LINENUMBER (9) LINENUMBER (9)
INVOKEINTERFACE (kotlinx/serialization/CompositeDecoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) INVOKEINTERFACE (kotlinx/serialization/CompositeDecoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V)
NEW NEW
@@ -419,7 +417,7 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
CHECKCAST CHECKCAST
INVOKESPECIAL (OptionalUser, <init>, (ILUser;Lkotlinx/serialization/SerializationConstructorMarker;)V) INVOKESPECIAL (OptionalUser, <init>, (ILUser;Lkotlinx/serialization/SerializationConstructorMarker;)V)
ARETURN ARETURN
LABEL (L10) LABEL (L9)
} }
public java.lang.Object deserialize(kotlinx.serialization.Decoder decoder) { public java.lang.Object deserialize(kotlinx.serialization.Decoder decoder) {
@@ -624,6 +622,7 @@ public final class OptionalUser : java/lang/Object {
CHECKCAST CHECKCAST
ICONST_1 ICONST_1
ACONST_NULL ACONST_NULL
CHECKCAST
INVOKESPECIAL (OptionalUser, <init>, (LUser;ILkotlin/jvm/internal/DefaultConstructorMarker;)V) INVOKESPECIAL (OptionalUser, <init>, (LUser;ILkotlin/jvm/internal/DefaultConstructorMarker;)V)
RETURN RETURN
LABEL (L1) LABEL (L1)
@@ -678,16 +677,18 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
LINENUMBER (6) LINENUMBER (6)
ICONST_2 ICONST_2
ANEWARRAY ANEWARRAY
DUP ASTORE (1)
ALOAD (1)
ICONST_0 ICONST_0
GETSTATIC (INSTANCE, Lkotlinx/serialization/internal/StringSerializer;) GETSTATIC (INSTANCE, Lkotlinx/serialization/internal/StringSerializer;)
CHECKCAST CHECKCAST
AASTORE AASTORE
DUP ALOAD (1)
ICONST_1 ICONST_1
GETSTATIC (INSTANCE, Lkotlinx/serialization/internal/StringSerializer;) GETSTATIC (INSTANCE, Lkotlinx/serialization/internal/StringSerializer;)
CHECKCAST CHECKCAST
AASTORE AASTORE
ALOAD (1)
ARETURN ARETURN
LABEL (L1) LABEL (L1)
} }
@@ -728,13 +729,10 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
ILOAD (4) ILOAD (4)
TABLESWITCH TABLESWITCH
LABEL (L4) LABEL (L4)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, throwNpe, ()V)
GOTO (L5)
LABEL (L6)
ICONST_0 ICONST_0
ISTORE (3) ISTORE (3)
GOTO (L5) GOTO (L5)
LABEL (L7) LABEL (L6)
ALOAD (8) ALOAD (8)
ALOAD (2) ALOAD (2)
ICONST_0 ICONST_0
@@ -746,7 +744,7 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
IOR IOR
ISTORE (5) ISTORE (5)
GOTO (L5) GOTO (L5)
LABEL (L8) LABEL (L7)
ALOAD (8) ALOAD (8)
ALOAD (2) ALOAD (2)
ICONST_1 ICONST_1
@@ -758,7 +756,7 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
IOR IOR
ISTORE (5) ISTORE (5)
GOTO (L5) GOTO (L5)
LABEL (L9) LABEL (L8)
NEW NEW
DUP DUP
ILOAD (4) ILOAD (4)
@@ -771,7 +769,7 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
LABEL (L3) LABEL (L3)
ALOAD (8) ALOAD (8)
ALOAD (2) ALOAD (2)
LABEL (L10) LABEL (L9)
LINENUMBER (6) LINENUMBER (6)
INVOKEINTERFACE (kotlinx/serialization/CompositeDecoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) INVOKEINTERFACE (kotlinx/serialization/CompositeDecoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V)
NEW NEW
@@ -785,7 +783,7 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
CHECKCAST CHECKCAST
INVOKESPECIAL (User, <init>, (ILjava/lang/String;Ljava/lang/String;Lkotlinx/serialization/SerializationConstructorMarker;)V) INVOKESPECIAL (User, <init>, (ILjava/lang/String;Ljava/lang/String;Lkotlinx/serialization/SerializationConstructorMarker;)V)
ARETURN ARETURN
LABEL (L11) LABEL (L10)
} }
public java.lang.Object deserialize(kotlinx.serialization.Decoder decoder) { public java.lang.Object deserialize(kotlinx.serialization.Decoder decoder) {