From bf60819824de22d49684122ffec79968101bf8a4 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Mon, 2 Jan 2023 20:51:11 +0100 Subject: [PATCH] Check for name when searching Companion.serializer() function to generate Name check was forgotten during refactoring, so any user function with matching signature could be overwritten by the plugin, while correct function would not have body. #KT-55682 Fixed --- .../ir/SerializableCompanionIrGenerator.kt | 25 ++++++++----- .../boxIr/userDefinedSerializerInCompanion.kt | 37 +++++++++++++++++++ ...SerializationFirBlackBoxTestGenerated.java | 6 +++ .../SerializationIrBoxTestGenerated.java | 6 +++ 4 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 plugins/kotlinx-serialization/testData/boxIr/userDefinedSerializerInCompanion.kt diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt index 7d15195bfe4..b780031f1a3 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt @@ -35,10 +35,13 @@ class SerializableCompanionIrGenerator( companion object { fun getSerializerGetterFunction(serializableIrClass: IrClass): IrSimpleFunction? { - val irClass = if (serializableIrClass.isSerializableObject) serializableIrClass else serializableIrClass.companionObject() ?: return null + val irClass = + if (serializableIrClass.isSerializableObject) serializableIrClass else serializableIrClass.companionObject() ?: return null return irClass.findDeclaration { - (it.valueParameters.size == serializableIrClass.typeParameters.size - && it.valueParameters.all { p -> p.type.isKSerializer() }) && it.returnType.isKSerializer() + it.name == SerialEntityNames.SERIALIZER_PROVIDER_NAME + && it.valueParameters.size == serializableIrClass.typeParameters.size + && it.valueParameters.all { p -> p.type.isKSerializer() } + && it.returnType.isKSerializer() } } @@ -57,10 +60,12 @@ class SerializableCompanionIrGenerator( } fun generate() { - val serializerGetterFunction = getSerializerGetterFunction(serializableIrClass) ?: throw IllegalStateException( - "Can't find synthesized 'Companion.serializer()' function to generate, " + - "probably clash with user-defined function has occurred" - ) + val serializerGetterFunction = + getSerializerGetterFunction(serializableIrClass)?.takeIf { it.isFromPlugin(compilerContext.afterK2) } + ?: throw IllegalStateException( + "Can't find synthesized 'Companion.serializer()' function to generate, " + + "probably clash with user-defined function has occurred" + ) if (serializableIrClass.isSerializableObject || serializableIrClass.isAbstractOrSealedSerializableClass @@ -115,7 +120,8 @@ class SerializableCompanionIrGenerator( ) ) - val kSerializerIrClass = compilerContext.referenceClass(ClassId(SerializationPackages.packageFqName, SerialEntityNames.KSERIALIZER_NAME))!!.owner + val kSerializerIrClass = + compilerContext.referenceClass(ClassId(SerializationPackages.packageFqName, SerialEntityNames.KSERIALIZER_NAME))!!.owner val targetIrType = kSerializerIrClass.defaultType.substitute(mapOf(kSerializerIrClass.typeParameters[0].symbol to compilerContext.irBuiltIns.anyType)) @@ -154,7 +160,8 @@ class SerializableCompanionIrGenerator( private fun getOrCreateSerializerVarargFactory(): IrSimpleFunction { irClass.findDeclaration { - it.valueParameters.size == 1 + it.name == SerialEntityNames.SERIALIZER_PROVIDER_NAME + && it.valueParameters.size == 1 && it.valueParameters.first().isVararg && it.returnType.isKSerializer() && it.isFromPlugin(compilerContext.afterK2) diff --git a/plugins/kotlinx-serialization/testData/boxIr/userDefinedSerializerInCompanion.kt b/plugins/kotlinx-serialization/testData/boxIr/userDefinedSerializerInCompanion.kt new file mode 100644 index 00000000000..d6a3532d7bb --- /dev/null +++ b/plugins/kotlinx-serialization/testData/boxIr/userDefinedSerializerInCompanion.kt @@ -0,0 +1,37 @@ +// TARGET_BACKEND: JVM_IR + +// WITH_STDLIB + +import kotlinx.serialization.* +import kotlinx.serialization.descriptors.* +import kotlinx.serialization.builtins.* + + +@Serializable +data class Main(val fields: MainFields) { + companion object { + fun fieldsSerializer(): KSerializer = MainFields.serializer() + } +} + +@Serializable +data class MainFields(val firstName: String?) + +@Serializable +data class Box(val boxed: T) { + companion object { + fun serializerLike(tSer: KSerializer): KSerializer>> = ListSerializer(serializer(tSer)) + } +} + + +fun box(): String { + if (Main.fieldsSerializer().descriptor.toString() != "MainFields(firstName: kotlin.String?)") return "Error1" + if (MainFields.serializer().descriptor.toString() != "MainFields(firstName: kotlin.String?)") return "Error2" + if (Main.serializer().descriptor.toString() != "Main(fields: MainFields)") return "Error3" + val boxListDesc = Box.serializerLike(String.serializer()).descriptor + if (boxListDesc.toString() != "kotlin.collections.ArrayList(Box(boxed: kotlin.String))") return boxListDesc.toString() + val boxDesc = Box.serializer(String.serializer()).descriptor + if (boxDesc.toString() != "Box(boxed: kotlin.String)") return boxDesc.toString() + return "OK" +} \ No newline at end of file diff --git a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationFirBlackBoxTestGenerated.java b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationFirBlackBoxTestGenerated.java index 0eb5e4d47f8..b0db2c69dbe 100644 --- a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationFirBlackBoxTestGenerated.java +++ b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationFirBlackBoxTestGenerated.java @@ -158,6 +158,12 @@ public class SerializationFirBlackBoxTestGenerated extends AbstractSerialization public void testUseSerializersChain() throws Exception { runTest("plugins/kotlinx-serialization/testData/boxIr/useSerializersChain.kt"); } + + @Test + @TestMetadata("userDefinedSerializerInCompanion.kt") + public void testUserDefinedSerializerInCompanion() throws Exception { + runTest("plugins/kotlinx-serialization/testData/boxIr/userDefinedSerializerInCompanion.kt"); + } } @Nested diff --git a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationIrBoxTestGenerated.java b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationIrBoxTestGenerated.java index 50a26920d25..f8d70a3ea86 100644 --- a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationIrBoxTestGenerated.java +++ b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationIrBoxTestGenerated.java @@ -156,4 +156,10 @@ public class SerializationIrBoxTestGenerated extends AbstractSerializationIrBoxT public void testUseSerializersChain() throws Exception { runTest("plugins/kotlinx-serialization/testData/boxIr/useSerializersChain.kt"); } + + @Test + @TestMetadata("userDefinedSerializerInCompanion.kt") + public void testUserDefinedSerializerInCompanion() throws Exception { + runTest("plugins/kotlinx-serialization/testData/boxIr/userDefinedSerializerInCompanion.kt"); + } }