From a024eedfaf45afa78054a8b43259463a0785e415 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Mon, 3 Mar 2025 12:58:43 +0100 Subject: [PATCH] Supply proper equals(), hashCode(), and toString() for SerialDescriptor() wrapper. Fixes #2941 --- .../descriptors/SerialDescriptors.kt | 27 ++++++++++++++----- .../PluginGeneratedSerialDescriptor.kt | 10 +++---- .../WrappedSerialDescriptorTest.kt | 10 +++++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/core/commonMain/src/kotlinx/serialization/descriptors/SerialDescriptors.kt b/core/commonMain/src/kotlinx/serialization/descriptors/SerialDescriptors.kt index 339ac3b783..67d872f2c5 100644 --- a/core/commonMain/src/kotlinx/serialization/descriptors/SerialDescriptors.kt +++ b/core/commonMain/src/kotlinx/serialization/descriptors/SerialDescriptors.kt @@ -121,7 +121,25 @@ public fun SerialDescriptor(serialName: String, original: SerialDescriptor): Ser return WrappedSerialDescriptor(serialName, original) } -internal class WrappedSerialDescriptor(override val serialName: String, original: SerialDescriptor) : SerialDescriptor by original +internal class WrappedSerialDescriptor(override val serialName: String, private val original: SerialDescriptor) : + SerialDescriptor by original { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is WrappedSerialDescriptor) return false + + return serialName == other.serialName && original == other.original + } + + override fun hashCode(): Int { + var result = serialName.hashCode() + result = 31 * result + original.hashCode() + return result + } + + override fun toString(): String = toStringImpl() + +} /** * An unsafe alternative to [buildClassSerialDescriptor] that supports an arbitrary [SerialKind]. @@ -370,10 +388,5 @@ internal class SerialDescriptorImpl( override fun hashCode(): Int = _hashCode - override fun toString(): String { - return (0 until elementsCount).joinToString(", ", prefix = "$serialName(", postfix = ")") { - getElementName(it) + ": " + getElementDescriptor(it).serialName - } - } + override fun toString(): String = toStringImpl() } - diff --git a/core/commonMain/src/kotlinx/serialization/internal/PluginGeneratedSerialDescriptor.kt b/core/commonMain/src/kotlinx/serialization/internal/PluginGeneratedSerialDescriptor.kt index a954bdab00..97e66943cb 100644 --- a/core/commonMain/src/kotlinx/serialization/internal/PluginGeneratedSerialDescriptor.kt +++ b/core/commonMain/src/kotlinx/serialization/internal/PluginGeneratedSerialDescriptor.kt @@ -96,11 +96,7 @@ internal open class PluginGeneratedSerialDescriptor( override fun hashCode(): Int = _hashCode - override fun toString(): String { - return (0 until elementsCount).joinToString(", ", "$serialName(", ")") { i -> - getElementName(i) + ": " + getElementDescriptor(i).serialName - } - } + override fun toString(): String = toStringImpl() } @OptIn(ExperimentalSerializationApi::class) @@ -131,3 +127,7 @@ internal fun SerialDescriptor.hashCodeImpl(typeParams: Array): result = 31 * result + kindHash return result } + +internal fun SerialDescriptor.toStringImpl(): String = (0 until elementsCount).joinToString(", ", "$serialName(", ")") { i -> + getElementName(i) + ": " + getElementDescriptor(i).serialName +} diff --git a/core/commonTest/src/kotlinx/serialization/WrappedSerialDescriptorTest.kt b/core/commonTest/src/kotlinx/serialization/WrappedSerialDescriptorTest.kt index 31303af18b..ff7ea2a73b 100644 --- a/core/commonTest/src/kotlinx/serialization/WrappedSerialDescriptorTest.kt +++ b/core/commonTest/src/kotlinx/serialization/WrappedSerialDescriptorTest.kt @@ -75,4 +75,14 @@ class WrappedSerialDescriptorTest { } assertFails { SerialDescriptor("kotlin.Int", Int.serializer().descriptor) } } + + @Test + fun testWrappedEqHc() { + val a = SerialDescriptor("SimpleTypeWrapper", SimpleType.serializer().descriptor) + val b = SerialDescriptor("SimpleTypeWrapper", SimpleType.serializer().descriptor) + assertEquals(a, b) + assertEquals(a.hashCode(), b.hashCode()) + assertNotEquals(a, SimpleType.serializer().descriptor) + assertEquals(a.toString(), "SimpleTypeWrapper(int: kotlin.Int, float: kotlin.Float)") + } }