Fix incorrect class reference in polymorphic and contextual case
Upper bound should be used for type parameters there
This commit is contained in:
+7
-7
@@ -379,11 +379,11 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
when (serializerClassOriginal.owner.classId) {
|
||||
polymorphicSerializerId -> {
|
||||
needToCopyAnnotations = true
|
||||
args = listOf(classReference(kType))
|
||||
args = listOf(classReference(kType.classOrUpperBound()!!))
|
||||
typeArgs = listOf(thisIrType)
|
||||
}
|
||||
contextSerializerId -> {
|
||||
args = listOf(classReference(kType))
|
||||
args = listOf(classReference(kType.classOrUpperBound()!!))
|
||||
typeArgs = listOf(thisIrType)
|
||||
|
||||
val hasNewCtxSerCtor = compilerContext.referenceConstructors(contextSerializerId).any { it.owner.valueParameters.size == 3 }
|
||||
@@ -412,16 +412,16 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
}
|
||||
objectSerializerId -> {
|
||||
needToCopyAnnotations = true
|
||||
args = listOf(irString(kType.serialName()), irGetObject(kType.classOrNull!!))
|
||||
args = listOf(irString(kType.serialName()), irGetObject(kType.classOrUpperBound()!!))
|
||||
typeArgs = listOf(thisIrType)
|
||||
}
|
||||
sealedSerializerId -> {
|
||||
needToCopyAnnotations = true
|
||||
args = mutableListOf<IrExpression>().apply {
|
||||
add(irString(kType.serialName()))
|
||||
add(classReference(kType))
|
||||
add(classReference(kType.classOrUpperBound()!!))
|
||||
val (subclasses, subSerializers) = allSealedSerializableSubclassesFor(
|
||||
kType.classOrNull!!.owner,
|
||||
kType.classOrUpperBound()!!.owner,
|
||||
pluginContext
|
||||
)
|
||||
val projectedOutCurrentKClass =
|
||||
@@ -431,7 +431,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
add(
|
||||
createArrayOfExpression(
|
||||
projectedOutCurrentKClass,
|
||||
subclasses.map { classReference(it) }
|
||||
subclasses.map { classReference(it.classOrUpperBound()!!) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
@@ -528,7 +528,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
}
|
||||
|
||||
// If KType is interface, .classSerializer always yields PolymorphicSerializer, which may be unavailable for interfaces from other modules
|
||||
if (!kType.isInterface() && serializerClassOriginal == kType.classOrNull!!.owner.classSerializer(pluginContext) && this@BaseIrGenerator !is SerializableCompanionIrGenerator) {
|
||||
if (!kType.isInterface() && serializerClassOriginal == kType.classOrUpperBound()?.owner.classSerializer(pluginContext) && this@BaseIrGenerator !is SerializableCompanionIrGenerator) {
|
||||
// This is default type serializer, we can shortcut through Companion.serializer()
|
||||
// BUT not during generation of this method itself
|
||||
callSerializerFromCompanion(thisIrType, typeArgs, args)?.let { return it }
|
||||
|
||||
+7
-5
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
@@ -506,8 +507,8 @@ interface IrBuilderWithPluginContext {
|
||||
)
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.classReference(classSymbol: IrType): IrClassReference =
|
||||
createClassReference(classSymbol, startOffset, endOffset)
|
||||
fun IrBuilderWithScope.classReference(classSymbol: IrClassSymbol): IrClassReference =
|
||||
createClassReference(classSymbol.starProjectedType, startOffset, endOffset)
|
||||
|
||||
fun collectSerialInfoAnnotations(irClass: IrClass): List<IrConstructorCall> {
|
||||
if (!(irClass.isInterface || irClass.descriptor.hasSerializableOrMetaAnnotation)) return emptyList()
|
||||
@@ -555,14 +556,15 @@ interface IrBuilderWithPluginContext {
|
||||
if (compilerContext.platform.isJvm()) {
|
||||
// "Byte::class" -> "java.lang.Byte::class"
|
||||
// TODO: get rid of descriptor
|
||||
val wrapperFqName = KotlinBuiltIns.getPrimitiveType(classType.classOrNull!!.descriptor)?.let(JvmPrimitiveType::get)?.wrapperFqName
|
||||
val wrapperFqName =
|
||||
KotlinBuiltIns.getPrimitiveType(classType.classOrNull!!.descriptor)?.let(JvmPrimitiveType::get)?.wrapperFqName
|
||||
if (wrapperFqName != null) {
|
||||
val wrapperClass = compilerContext.referenceClass(ClassId.topLevel(wrapperFqName))
|
||||
?: error("Primitive wrapper class for $classType not found: $wrapperFqName")
|
||||
return classReference(wrapperClass.defaultType)
|
||||
return createClassReference(wrapperClass.defaultType, startOffset, endOffset)
|
||||
}
|
||||
}
|
||||
return classReference(classType)
|
||||
return createClassReference(classType, startOffset, endOffset)
|
||||
}
|
||||
|
||||
fun IrClass.getSuperClassOrAny(): IrClass = getSuperClassNotAny() ?: compilerContext.irBuiltIns.anyClass.owner
|
||||
|
||||
+10
-1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.getStringConstArgument
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
@@ -108,7 +110,7 @@ internal fun IrClass.isSerializableEnum(): Boolean = kind == ClassKind.ENUM_CLAS
|
||||
internal val IrType.genericIndex: Int?
|
||||
get() = (this.classifierOrNull as? IrTypeParameterSymbol)?.owner?.index
|
||||
|
||||
fun IrType.serialName(): String = this.classOrNull!!.owner.serialName()
|
||||
fun IrType.serialName(): String = this.classOrUpperBound()!!.owner.serialName()
|
||||
|
||||
fun IrClass.serialName(): String {
|
||||
return annotations.serialNameValue ?: fqNameWhenAvailable?.asString() ?: error("${this.render()} does not have fqName")
|
||||
@@ -199,4 +201,11 @@ fun findSerializerConstructorForTypeArgumentsSerializers(serializer: IrClass): I
|
||||
return serializer.constructors.singleOrNull {
|
||||
it.valueParameters.let { vps -> vps.size == typeParamsCount && vps.all { vp -> vp.type.isKSerializer() } }
|
||||
}?.symbol
|
||||
}
|
||||
|
||||
fun IrType.classOrUpperBound(): IrClassSymbol? = when(val cls = classifierOrNull) {
|
||||
is IrClassSymbol -> cls
|
||||
is IrScriptSymbol -> cls.owner.targetClass
|
||||
is IrTypeParameterSymbol -> cls.owner.representativeUpperBound.classOrUpperBound()
|
||||
else -> null
|
||||
}
|
||||
-24
@@ -63,28 +63,4 @@ fun FirDeclarationGenerationExtension.buildConstructor(classId: ClassId, isInner
|
||||
}.also {
|
||||
it.containingClassForStaticMemberAttr = lookupTag
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: copied from Parcelize plugin
|
||||
inline fun FirSession.createFunction(
|
||||
owner: FirRegularClassSymbol,
|
||||
callableId: CallableId,
|
||||
init: FirSimpleFunctionBuilder.() -> Unit
|
||||
): FirNamedFunctionSymbol {
|
||||
val function = buildSimpleFunction {
|
||||
moduleData = this@createFunction.moduleData
|
||||
origin = SerializationPluginKey.origin
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
if (owner.modality == Modality.FINAL) Modality.FINAL else Modality.OPEN,
|
||||
EffectiveVisibility.Public
|
||||
).apply {
|
||||
isOverride = true
|
||||
}
|
||||
name = callableId.callableName
|
||||
symbol = FirNamedFunctionSymbol(callableId)
|
||||
dispatchReceiverType = owner.defaultType()
|
||||
init()
|
||||
}
|
||||
return function.symbol
|
||||
}
|
||||
Reference in New Issue
Block a user