Skip to content

Commit

Permalink
Do not create cacheableChildSerializers unless it is necessary
Browse files Browse the repository at this point in the history
Creation of this property in the SerializerIrGenerator.<init> can lead to
a 'Serializer not found' internal error when generator is applied to a fully-customized external serializer.
In that case, generator is still created, but none of the generateSave/Load functions are called,
so cacheableChildSerializers(Property) is not necessary.

#KT-57730 Fixed
Fixes Kotlin/kotlinx.serialization#2260

(cherry picked from commit d9e16fb)
  • Loading branch information
sandwwraith authored and Space Team committed Apr 19, 2023
1 parent 9f94142 commit a75271c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 10 deletions.
Expand Up @@ -66,11 +66,9 @@ open class SerializerIrGenerator(
SerialEntityNames.SERIAL_DESC_FIELD
) { true }?.takeIf { it.isFromPlugin(compilerContext.afterK2) }

protected val anySerialDescProperty = getProperty(
protected val irAnySerialDescProperty = getProperty(
SerialEntityNames.SERIAL_DESC_FIELD,
) { true } // remove true?

protected val irAnySerialDescProperty = anySerialDescProperty
) { true }

fun getProperty(
name: String,
Expand All @@ -83,13 +81,16 @@ open class SerializerIrGenerator(
private set

// child serializers cached if serializable class is internal
private val cachedChildSerializersProperty = if (isGeneratedSerializer)
serializableIrClass.companionObject()?.properties?.singleOrNull { it.name == CACHED_CHILD_SERIALIZERS_PROPERTY_NAME }
else null
private val cachedChildSerializersProperty by lazy {
if (isGeneratedSerializer)
serializableIrClass.companionObject()?.properties?.singleOrNull { it.name == CACHED_CHILD_SERIALIZERS_PROPERTY_NAME }
else null
}

// non-object serializers which can be cached
private val cacheableChildSerializers =
private val cacheableChildSerializers by lazy {
serializableIrClass.createCachedChildSerializers(properties.serializableProperties).map { it != null }
}

// null if was not found — we're in FIR
private fun findLocalSerializersFieldDescriptors(): List<IrProperty?> {
Expand Down Expand Up @@ -230,7 +231,12 @@ open class SerializerIrGenerator(

val allSerializers = serializableProperties.mapIndexed { index, property ->
requireNotNull(
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, property, cachedChildSerializerByIndex(index))
serializerTower(
this@SerializerIrGenerator,
irFun.dispatchReceiverParameter!!,
property,
cachedChildSerializerByIndex(index)
)
) { "Property ${property.name} must have a serializer" }
}

Expand Down
Expand Up @@ -25,4 +25,4 @@ object URLSerializer : KSerializer<URL> {
fun box(): String {
if (URLSerializer.descriptor.toString() != "PrimitiveDescriptor(java.net.URL)") return URLSerializer.descriptor.toString()
return "OK"
}
}
@@ -0,0 +1,30 @@
// TARGET_BACKEND: JVM_IR

// FULL_JDK
// WITH_STDLIB

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import java.math.BigDecimal

@Serializable(with = DataBigDecimal.Serializer::class)
data class DataBigDecimal(val value: BigDecimal) {

@kotlinx.serialization.Serializer(forClass = DataBigDecimal::class)
object Serializer : KSerializer<DataBigDecimal> {

override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("my.DataBigDecimal", PrimitiveKind.STRING)

override fun deserialize(decoder: Decoder): DataBigDecimal =
TODO()

override fun serialize(encoder: Encoder, value: DataBigDecimal): Unit =
TODO()
}
}

fun box(): String {
if (DataBigDecimal.Serializer.descriptor.toString() != "PrimitiveDescriptor(my.DataBigDecimal)") return DataBigDecimal.Serializer.descriptor.toString()
return "OK"
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a75271c

Please sign in to comment.