From 63025030e3c66c234b2ace02dd24cbef599f11f1 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 22 Feb 2023 19:38:18 +0000 Subject: [PATCH] [KxSerialization] Fix SERIALIZER_NOT_FOUND diagnostic for enums Fixes #KT-56738 Merge-request: KT-MR-8938 Merged-by: Sergey Shanshin --- .../compiler/backend/ir/IrPredicates.kt | 18 ++++++++++++++---- .../backend/ir/SerializerIrGenerator.kt | 2 +- .../backend/ir/SerializerSearchUtil.kt | 14 +++++++++----- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPredicates.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPredicates.kt index d672da3ab71..04a8bd636cc 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPredicates.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPredicates.kt @@ -63,7 +63,17 @@ internal fun IrClass.findPluginGeneratedMethod(name: String, afterK2: Boolean): } } -internal fun IrClass.isEnumWithLegacyGeneratedSerializer(context: SerializationBaseContext): Boolean = isInternallySerializableEnum() && !context.runtimeHasEnumSerializerFactoryFunctions +internal fun IrClass.isEnumWithLegacyGeneratedSerializer(): Boolean { + return findEnumLegacySerializer() != null +} + +internal fun IrClass.findEnumLegacySerializer(): IrClass? { + return if (kind == ClassKind.ENUM_CLASS) { + declarations.filterIsInstance().singleOrNull { it.name == SerialEntityNames.SERIALIZER_CLASS_NAME } + } else { + null + } +} internal val IrClass.isSealedSerializableInterface: Boolean get() = kind == ClassKind.INTERFACE && modality == Modality.SEALED && hasSerializableOrMetaAnnotation() @@ -102,9 +112,9 @@ internal val IrClass.isSerialInfoAnnotation: Boolean internal val IrClass.isInheritableSerialInfoAnnotation: Boolean get() = annotations.hasAnnotation(SerializationAnnotations.inheritableSerialInfoFqName) -internal fun IrClass.shouldHaveGeneratedSerializer(context: SerializationBaseContext): Boolean - = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN)) - || isEnumWithLegacyGeneratedSerializer(context) +internal fun IrClass.shouldHaveGeneratedSerializer(): Boolean = + (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN)) + || isEnumWithLegacyGeneratedSerializer() internal val IrClass.shouldHaveGeneratedMethodsInCompanion: Boolean get() = this.isSerializableObject || this.isSerializableEnum() || (this.kind == ClassKind.CLASS && hasSerializableOrMetaAnnotation()) || this.isSealedSerializableInterface diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt index 020cbfc2790..5755942c540 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt @@ -630,7 +630,7 @@ open class SerializerIrGenerator( ) { val serializableDesc = context.getSerializableClassDescriptorBySerializer(irClass) ?: return val generator = when { - serializableDesc.isEnumWithLegacyGeneratedSerializer(context) -> SerializerForEnumsGenerator( + serializableDesc.isEnumWithLegacyGeneratedSerializer() -> SerializerForEnumsGenerator( irClass, context ) diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerSearchUtil.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerSearchUtil.kt index 448df314301..702e6e8daf3 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerSearchUtil.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerSearchUtil.kt @@ -127,9 +127,13 @@ fun findTypeSerializer(context: SerializationBaseContext, type: IrType): IrClass fun findEnumTypeSerializer(context: SerializationBaseContext, type: IrType): IrClassSymbol? { val classSymbol = type.classOrNull?.owner ?: return null - return if (classSymbol.kind == ClassKind.ENUM_CLASS && !classSymbol.isEnumWithLegacyGeneratedSerializer(context)) - context.referenceClassId(enumSerializerId) - else null + + // in any case, the function returns the serializer for the enum + if (classSymbol.kind != ClassKind.ENUM_CLASS) return null + + val legacySerializer = classSymbol.findEnumLegacySerializer() + // $serializer for legacy compiled enums, or EnumSerializer for factories + return legacySerializer?.symbol ?: context.referenceClassId(enumSerializerId) } internal fun IrClass?.classSerializer(context: SerializationBaseContext): IrClassSymbol? = this?.let { @@ -140,7 +144,7 @@ internal fun IrClass?.classSerializer(context: SerializationBaseContext): IrClas // can infer @Poly? polymorphicSerializerIfApplicableAutomatically(context)?.let { return it } // default serializable? - if (shouldHaveGeneratedSerializer(context)) { + if (shouldHaveGeneratedSerializer()) { // $serializer nested class return this.declarations .filterIsInstance() @@ -237,7 +241,7 @@ internal fun SerializationBaseContext.getSerializableClassDescriptorBySerializer ) ) return null val classDescriptor = (serializer.parent as? IrClass) ?: return null - if (!classDescriptor.shouldHaveGeneratedSerializer(this)) return null + if (!classDescriptor.shouldHaveGeneratedSerializer()) return null return classDescriptor }