@@ -10,8 +10,10 @@ import org.jetbrains.kotlin.descriptors.ClassKind
1010import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
1111import org.jetbrains.kotlin.ir.builders.*
1212import org.jetbrains.kotlin.ir.declarations.IrClass
13+ import org.jetbrains.kotlin.ir.declarations.IrConstructor
1314import org.jetbrains.kotlin.ir.expressions.IrClassReference
1415import org.jetbrains.kotlin.ir.expressions.IrExpression
16+ import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
1517import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
1618import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
1719import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
@@ -28,7 +30,6 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.
2830import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.polymorphicSerializerId
2931import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.referenceArraySerializerId
3032import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.sealedSerializerId
31- import kotlin.collections.orEmpty
3233
3334internal class Instantiator (
3435 val generator : BaseIrGenerator ,
@@ -50,7 +51,6 @@ internal class Instantiator(
5051
5152 data class Args (
5253 val args : List <IrExpression >, val typeArgs : List <IrType >,
53- val useCompanionShortcut : Boolean , val needToCopyAnnotations : Boolean ,
5454 )
5555
5656 context(irBuilder: IrBuilderWithScope )
@@ -70,60 +70,80 @@ internal class Instantiator(
7070 kType as ? IrSimpleType ? : error(" Don't know how to work with type ${kType::class } " )
7171 val typeArgumentsAsTypes = kType.argumentTypesOrUpperBounds()
7272
73- val args = when (serializerClass.owner.classId) {
74- polymorphicSerializerId -> Args (listOf (classReferenceOf(kType)), listOf (kType), false , true )
75- contextSerializerId -> {
76- doContextSerializer(kType, genericIndex, typeArgumentsAsTypes) ? : return null
77- }
73+ val needToCopyAnnotations = serializerClass.owner.classId.let { it == polymorphicSerializerId || it == objectSerializerId }
74+
75+ // If KType is interface, .classSerializer always yields PolymorphicSerializer, which may be unavailable for interfaces from other modules
76+ val canUseShortcut =
77+ ! kType.isInterface() && serializerClass == kType.classOrUpperBound()?.owner.classSerializer(compilerContext) && generator !is SerializableCompanionIrGenerator
78+
79+ var ctor: IrConstructor ? = null
80+
81+ val (args, typeArgs) = when (serializerClass.owner.classId) {
82+ polymorphicSerializerId -> Args (listOf (classReferenceOf(kType)), listOf (kType))
83+ contextSerializerId -> argsForContextSerializer(kType, genericIndex, typeArgumentsAsTypes) ? : return null
7884 objectSerializerId -> Args (
7985 args = listOf (irBuilder.irString(kType.serialName()), irBuilder.irGetObject(kType.classOrUpperBound()!! )),
8086 typeArgs = listOf (kType),
81- useCompanionShortcut = false ,
82- needToCopyAnnotations = true ,
8387 )
84- sealedSerializerId -> doSealed (serializerClass, kType)
88+ sealedSerializerId -> return instantiateSealedSerializer (serializerClass, kType)
8589 enumSerializerId -> return instantiateEnumSerializer(kType)
8690 referenceArraySerializerId -> {
8791 val (origArgs, origTypeArgs) = regularArgs(typeArgumentsAsTypes) ? : return null
8892 val args = listOf (generator.wrapperClassReference(typeArgumentsAsTypes.single())) + origArgs
8993 val typeArgs = listOf (origTypeArgs[0 ].makeNotNull()) + origTypeArgs
90- Args (args, typeArgs, false , false )
94+ Args (args, typeArgs)
95+ }
96+ else -> {
97+ if (canUseShortcut) {
98+ regularArgs(typeArgumentsAsTypes) ? : return null
99+ } else {
100+ ctor = findConstructor(serializerClass, needToCopyAnnotations).owner
101+ val requiresArgs = ctor.parameters.isNotEmpty()
102+ if (! requiresArgs) Args (emptyList(), emptyList()) else regularArgs(typeArgumentsAsTypes) ? : return null
103+ }
91104 }
92- else -> regularArgs(typeArgumentsAsTypes) ? : return null
93105 }
94106
95- val canUseShortcut =
96- ! kType.isInterface() && serializerClass == kType.classOrUpperBound()?.owner.classSerializer(compilerContext) && generator !is SerializableCompanionIrGenerator
97- if (canUseShortcut || args.useCompanionShortcut) {
107+ if (canUseShortcut) {
98108 // This is default type serializer, we can shortcut through Companion.serializer()
99109 // BUT not during generation of this method itself
100- // TODO : check if we still want to build args for sealed/ polymorphic serializers here
101- generator.callSerializerFromCompanion(kType, args. typeArgs, args. args, serializerClass.owner.classId)?.let { return it }
110+ // For future : check if we still want to build args for polymorphic/object serializers here, likely not.
111+ generator.callSerializerFromCompanion(kType, typeArgs, args, serializerClass.owner.classId)?.let { return it }
102112 }
103113
114+ val newArgs = if (needToCopyAnnotations) addAnnotationsToArgs(kType, args) else args
104115
105- val needToCopyAnnotations = args.needToCopyAnnotations
106-
107- val ctor = findConstructor(serializerClass, needToCopyAnnotations)
108- val ctorDecl = ctor.owner
109-
110- val newArgs = if (needToCopyAnnotations) {
111- val classAnnotations =
112- generator.copyAnnotationsFrom(kType.getClass()?.let { generator.collectSerialInfoAnnotations(it) }.orEmpty())
113- args.args + generator.createArrayOfExpression(compilerContext.irBuiltIns.annotationType, classAnnotations)
114- } else args.args
116+ if (ctor == null ) ctor = findConstructor(serializerClass, needToCopyAnnotations).owner
117+ return callConstructor(ctor, typeArgs, newArgs)
118+ }
115119
116- val typeParameters = ctorDecl.parentAsClass.typeParameters
117- val substitutedReturnType = ctorDecl.returnType.substitute(typeParameters, args.typeArgs)
120+ context(irBuilder: IrBuilderWithScope )
121+ private fun callConstructor (
122+ ctor : IrConstructor ,
123+ typeArgs : List <IrType >,
124+ valueArgs : List <IrExpression >,
125+ ): IrFunctionAccessExpression {
126+ val typeParameters = ctor.parentAsClass.typeParameters
127+ val substitutedReturnType = ctor.returnType.substitute(typeParameters, typeArgs)
118128 return generator.irInvoke(
119- ctor,
129+ ctor.symbol ,
120130 // User may declare serializer with fixed type arguments, e.g. class SomeSerializer : KSerializer<ClosedRange<Float>>
121- arguments = newArgs .takeIf { it.size == ctorDecl .parameters.size }.orEmpty(),
122- typeArguments = args. typeArgs.takeIf { it.size == ctorDecl .typeParameters.size }.orEmpty(),
131+ arguments = valueArgs .takeIf { it.size == ctor .parameters.size }.orEmpty(),
132+ typeArguments = typeArgs.takeIf { it.size == ctor .typeParameters.size }.orEmpty(),
123133 returnTypeHint = substitutedReturnType
124134 )
125135 }
126136
137+ context(irBuilder: IrBuilderWithScope )
138+ private fun addAnnotationsToArgs (
139+ kType : IrSimpleType ,
140+ args : List <IrExpression >,
141+ ): List <IrExpression > {
142+ val classAnnotations =
143+ generator.copyAnnotationsFrom(kType.getClass()?.let { generator.collectSerialInfoAnnotations(it) }.orEmpty())
144+ return args + generator.createArrayOfExpression(compilerContext.irBuiltIns.annotationType, classAnnotations)
145+ }
146+
127147 private fun findConstructor (serializerClass : IrClassSymbol , needToCopyAnnotations : Boolean ): IrConstructorSymbol {
128148 val serializable = getSerializableClassDescriptorBySerializer(serializerClass.owner)
129149 val ctor = if (serializable?.typeParameters?.isNotEmpty() == true ) {
@@ -152,7 +172,7 @@ internal class Instantiator(
152172 context(irBuilder: IrBuilderWithScope )
153173 private fun classReferenceOf (kType : IrSimpleType ): IrClassReference = generator.classReference(kType.classOrUpperBound()!! )
154174
155- context(irBuilder: IrBuilderWithScope ) private fun doContextSerializer (
175+ context(irBuilder: IrBuilderWithScope ) private fun argsForContextSerializer (
156176 kType : IrSimpleType ,
157177 genericIndex : Int? ,
158178 typeArgumentsAsTypes : List <IrType >,
@@ -187,7 +207,7 @@ internal class Instantiator(
187207 })
188208 )
189209 }
190- return Args (args, typeArgs, false , false )
210+ return Args (args, typeArgs)
191211 }
192212
193213 context(irBuilder: IrBuilderWithScope ) private fun instantiateEnumSerializer (kType : IrSimpleType ): IrExpression {
@@ -248,13 +268,13 @@ internal class Instantiator(
248268 )
249269 instantiate(argSer, it) ? : return null
250270 }
251- return Args (args, typeArgumentsAsTypes, false , false )
271+ return Args (args, typeArgumentsAsTypes)
252272 }
253273
254- context(irBuilder: IrBuilderWithScope ) private fun doSealed (
274+ context(irBuilder: IrBuilderWithScope ) private fun instantiateSealedSerializer (
255275 serializerClass : IrClassSymbol ,
256276 kType : IrSimpleType ,
257- ): Args {
277+ ): IrExpression {
258278 val needToCopyAnnotations = true
259279 val typeArgs = listOf (kType)
260280
@@ -290,8 +310,7 @@ internal class Instantiator(
290310 }
291311 }
292312 }
293- return Args (args, typeArgs, true , false )
294- // generator.callSerializerFromCompanion(kType, typeArgs, args, sealedSerializerId)?.let { return TODO(it.toString()) }
313+ generator.callSerializerFromCompanion(kType, typeArgs, args, sealedSerializerId)?.let { return it }
295314 }
296315
297316
@@ -352,7 +371,10 @@ internal class Instantiator(
352371 )
353372 )
354373 }
355- return Args (args, typeArgs, false , needToCopyAnnotations)
374+ val newArgs = addAnnotationsToArgs(kType, args)
375+
376+ val ctor = findConstructorWithoutTypeParameters(serializerClass, needToCopyAnnotations).owner
377+ return callConstructor(ctor, typeArgs, newArgs)
356378 }
357379
358380 context(irBuilder: IrBuilderWithScope )
0 commit comments