From 18328f9f5e62313ddcf1a35205e01bfe4ceb5a85 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Mon, 7 Jun 2021 16:22:53 +0300 Subject: [PATCH] Create a copy of incorrectly deserialized parent's writeSelf function To avoid problems during code generation when INVOKEDYNAMIC is used instead of static #KT-47161 Fixed (cherry picked from commit dd213264256d9ea83b59b6656a1843fe930f83c8) --- .../backend/ir/SerializableIrGenerator.kt | 15 +++++++++++-- .../SerializationLoweringExtension.kt | 22 ++++++++++++------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt index 4ecb4ca49c106..9f05937985597 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt @@ -293,11 +293,22 @@ class SerializableIrGenerator( ignoreIndexTo = bindingContext.serializablePropertiesFor(superClass.descriptor).size // call super.writeSelf - val superWriteSelfF = superClass.findWriteSelfMethod() + var superWriteSelfF = superClass.findWriteSelfMethod() + if (superWriteSelfF != null) { + // Workaround for incorrect DeserializedClassDescriptor on JVM (see MemberDeserializer#getDispatchReceiverParameter): + // Because Kotlin does not have static functions, descriptors from other modules are deserialized with dispatch receiver, + // even if they were created without it + if (superWriteSelfF.dispatchReceiverParameter != null) { + superWriteSelfF = compilerContext.copiedStaticWriteSelf.getOrPut(superWriteSelfF) { + superWriteSelfF!!.deepCopyWithSymbols(initialParent = superClass).also { it.dispatchReceiverParameter = null } + } + } + val args = mutableListOf(irGet(objectToSerialize), irGet(localOutput), irGet(localSerialDesc)) - val typeArgsForParent = serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments + val typeArgsForParent = + serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments val parentWriteSelfSerializers = typeArgsForParent.map { arg -> val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(arg).let { if (it == -1) null else it } val serial = findTypeSerializerOrContext(serializableDescriptor.module, arg.type) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt index 909bc9342b84a..be2947a03dc22 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt @@ -10,9 +10,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -23,6 +21,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializableCompa import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializableIrGenerator import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver +import java.util.concurrent.ConcurrentHashMap /** * Copy of [runOnFilePostfix], but this implementation first lowers declaration, then its children. @@ -40,17 +39,24 @@ fun ClassLoweringPass.runOnFileInOrder(irFile: IrFile) { }) } -typealias SerializationPluginContext = IrPluginContext + +class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugin: SerializationDescriptorSerializerPlugin?) : + IrPluginContext by baseContext { + lateinit var serialInfoImplJvmIrGenerator: SerialInfoImplJvmIrGenerator + + internal val copiedStaticWriteSelf: MutableMap = ConcurrentHashMap() +} private class SerializerClassLowering( - val context: SerializationPluginContext, - val metadataPlugin: SerializationDescriptorSerializerPlugin? + baseContext: IrPluginContext, + metadataPlugin: SerializationDescriptorSerializerPlugin? ) : IrElementTransformerVoid(), ClassLoweringPass { - private val serialInfoJvmGenerator = SerialInfoImplJvmIrGenerator(context) + val context: SerializationPluginContext = SerializationPluginContext(baseContext, metadataPlugin) + private val serialInfoJvmGenerator = SerialInfoImplJvmIrGenerator(context).also { context.serialInfoImplJvmIrGenerator = it } override fun lower(irClass: IrClass) { SerializableIrGenerator.generate(irClass, context, context.bindingContext) - SerializerIrGenerator.generate(irClass, context, context.bindingContext, metadataPlugin, serialInfoJvmGenerator) + SerializerIrGenerator.generate(irClass, context, context.bindingContext, context.metadataPlugin, serialInfoJvmGenerator) SerializableCompanionIrGenerator.generate(irClass, context, context.bindingContext) if (context.platform.isJvm() && KSerializerDescriptorResolver.isSerialInfoImpl(irClass.descriptor)) {