From 2d1e8db9b93b742efb8de7aad43a708ee57f0e6c Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Tue, 17 Jan 2023 17:04:20 +0100 Subject: [PATCH] Handle @Serializable classes that implement interfaces by delegation by filtering out delegated properties that end up in irClass.properties() list Fixes https://github.com/Kotlin/kotlinx.serialization/issues/2157 (cherry picked from commit dc0cd61b6f60b1272514cb6585e7b75974fe02a9) --- .../backend/ir/IrSerializableProperties.kt | 3 ++- .../testData/boxIr/delegatedInterface.kt | 23 +++++++++++++++++++ ...SerializationFirBlackBoxTestGenerated.java | 6 +++++ .../SerializationIrBoxTestGenerated.java | 6 +++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 plugins/kotlinx-serialization/testData/boxIr/delegatedInterface.kt diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrSerializableProperties.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrSerializableProperties.kt index 90c252689470e..92a5f11fd919f 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrSerializableProperties.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrSerializableProperties.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.util.* @@ -78,7 +79,7 @@ internal fun serializablePropertiesForIrBackend( val (primaryCtorSerializableProps, bodySerializableProps) = properties .asSequence() - .filter { !it.isFakeOverride && !it.isDelegated } + .filter { !it.isFakeOverride && !it.isDelegated && it.origin != IrDeclarationOrigin.DELEGATED_MEMBER } .filter(::isPropSerializable) .map { val isConstructorParameterWithDefault = primaryParamsAsProps[it] ?: false diff --git a/plugins/kotlinx-serialization/testData/boxIr/delegatedInterface.kt b/plugins/kotlinx-serialization/testData/boxIr/delegatedInterface.kt new file mode 100644 index 0000000000000..8dcae4cb674d7 --- /dev/null +++ b/plugins/kotlinx-serialization/testData/boxIr/delegatedInterface.kt @@ -0,0 +1,23 @@ +// TARGET_BACKEND: JVM_IR + +// WITH_STDLIB + +import kotlinx.serialization.* +import kotlinx.serialization.descriptors.* +import kotlinx.serialization.encoding.* +import kotlinx.serialization.json.* + +@Serializable() +class Dto( + val data: Map +) : Map by data + +fun box(): String { + val dto = Dto(mapOf(1 to 2)) + val s = Json.encodeToString(dto) + if (s != """{"data":{"1":2}}""") return s + val d = Json.decodeFromString(s) + if (d.size != 1) return "Delegation to Map failed" + if (d.data != dto.data) return "Equals failed ${d.data}" + 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 bbeb6c5559c8d..295dd807b3d12 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 @@ -39,6 +39,12 @@ public void testClassSerializerAsObject() throws Exception { runTest("plugins/kotlinx-serialization/testData/boxIr/classSerializerAsObject.kt"); } + @Test + @TestMetadata("delegatedInterface.kt") + public void testDelegatedInterface() throws Exception { + runTest("plugins/kotlinx-serialization/testData/boxIr/delegatedInterface.kt"); + } + @Test @TestMetadata("enumsAreCached.kt") public void testEnumsAreCached() throws Exception { 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 e401e44971b7b..147bf57b118e9 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 @@ -37,6 +37,12 @@ public void testClassSerializerAsObject() throws Exception { runTest("plugins/kotlinx-serialization/testData/boxIr/classSerializerAsObject.kt"); } + @Test + @TestMetadata("delegatedInterface.kt") + public void testDelegatedInterface() throws Exception { + runTest("plugins/kotlinx-serialization/testData/boxIr/delegatedInterface.kt"); + } + @Test @TestMetadata("enumsAreCached.kt") public void testEnumsAreCached() throws Exception {