From cd931796bc25b5d08670844d23247e2589ec27d7 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Wed, 8 Apr 2020 18:51:35 +0300 Subject: [PATCH] [SERIALIZATION] Fix kotlinx.serialization plugin --- .../common/serialization/KotlinIrLinker.kt | 3 +- .../compiler/backend/ir/GeneratorHelpers.kt | 109 +++++++++++------- .../backend/ir/SerializerIrGenerator.kt | 5 +- 3 files changed, 71 insertions(+), 46 deletions(-) diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt index fa8685d978c..e25bfc66ad7 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt @@ -422,8 +422,7 @@ abstract class KotlinIrLinker( } protected open fun resolveModuleDeserializer(moduleDescriptor: ModuleDescriptor): IrModuleDeserializer { - return deserializersForModules[moduleDescriptor] ?: - error("No module deserializer found for $moduleDescriptor") + return deserializersForModules[moduleDescriptor] ?: error("No module deserializer found for $moduleDescriptor") } protected abstract fun createModuleDeserializer( diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index e2b87a02890..7f992d1065d 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -49,12 +49,23 @@ interface IrBuilderExtension { val compilerContext: SerializationPluginContext private fun IrClass.declareSimpleFunctionWithExternalOverrides(descriptor: FunctionDescriptor): IrSimpleFunction { - return compilerContext.symbolTable.declareSimpleFunction(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, descriptor) - .also { f -> - f.overriddenSymbols = descriptor.overriddenDescriptors.map { - compilerContext.symbolTable.referenceSimpleFunction(it.original) - } + val functionSymbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor) + val function = if (functionSymbol.isBound) functionSymbol.owner else { + compilerContext.symbolTable.declareSimpleFunction( + startOffset, + endOffset, + SERIALIZABLE_PLUGIN_ORIGIN, + descriptor + ).also { + it.parent = this + addMember(it) } + } + return function.also { f -> + f.overriddenSymbols = descriptor.overriddenDescriptors.map { + compilerContext.symbolTable.referenceSimpleFunction(it.original) + } + } } private fun createFunctionGenerator(): FunctionGenerator = with(compilerContext) { @@ -77,24 +88,17 @@ interface IrBuilderExtension { fun IrClass.contributeFunction( descriptor: FunctionDescriptor, - declareNew: Boolean = true, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit ) { - val f: IrSimpleFunction = if (declareNew) declareSimpleFunctionWithExternalOverrides( - descriptor - ) else compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner - f.parent = this - if (declareNew) { - f.buildWithScope { - createFunctionGenerator().generateFunctionParameterDeclarationsAndReturnType(f, null, null) - } + val f: IrSimpleFunction = declareSimpleFunctionWithExternalOverrides(descriptor) + f.buildWithScope { + createFunctionGenerator().generateFunctionParameterDeclarationsAndReturnType(f, null, null) } f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody( this.startOffset, this.endOffset ) { bodyGen(f) } - this.addMember(f) } fun IrClass.contributeConstructor( @@ -103,21 +107,32 @@ interface IrBuilderExtension { overwriteValueParameters: Boolean = false, bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit ) { - val c = if (declareNew) compilerContext.symbolTable.declareConstructor( - this.startOffset, - this.endOffset, - SERIALIZABLE_PLUGIN_ORIGIN, - descriptor - ) else compilerContext.symbolTable.referenceConstructor(descriptor).owner - c.parent = this + val ctorSymbol = compilerContext.symbolTable.referenceConstructor(descriptor) + val c = if (ctorSymbol.isBound) { + ctorSymbol.owner + } else { + compilerContext.symbolTable.declareConstructor( + this.startOffset, + this.endOffset, + SERIALIZABLE_PLUGIN_ORIGIN, + descriptor + ).also { + it.parent = this + addMember(it) + } + } + c.returnType = descriptor.returnType.toIrType() - if (declareNew || overwriteValueParameters) c.createParameterDeclarations( + if (declareNew || overwriteValueParameters) + c.createParameterDeclarations( receiver = null, overwriteValueParameters = overwriteValueParameters, copyTypeParameters = false ) - c.body = DeclarationIrBuilder(compilerContext, c.symbol, this.startOffset, this.endOffset).irBlockBody(this.startOffset, this.endOffset) { bodyGen(c) } - this.addMember(c) + c.body = DeclarationIrBuilder(compilerContext, c.symbol, this.startOffset, this.endOffset).irBlockBody( + this.startOffset, + this.endOffset + ) { bodyGen(c) } } fun IrBuilderWithScope.irInvoke( @@ -126,7 +141,7 @@ interface IrBuilderExtension { vararg args: IrExpression, typeHint: IrType? = null ): IrMemberAccessExpression { - val returnType = typeHint ?: callee.descriptor.returnType!!.toIrType() + val returnType = typeHint ?: callee.run { if (isBound) owner.returnType else descriptor.returnType!!.toIrType() } val call = irCall(callee, type = returnType) call.dispatchReceiver = dispatchReceiver args.forEachIndexed(call::putValueArgument) @@ -253,12 +268,15 @@ interface IrBuilderExtension { propertyDescriptor: PropertyDescriptor, propertyParent: IrClass ): IrProperty { - val irProperty = IrPropertyImpl( - propertyParent.startOffset, propertyParent.endOffset, - SERIALIZABLE_PLUGIN_ORIGIN, false, - propertyDescriptor - ) - irProperty.parent = propertyParent + val symbol = compilerContext.symbolTable.referenceProperty(propertyDescriptor) + val irProperty = if (symbol.isBound) symbol.owner else { + compilerContext.symbolTable.declareProperty(propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, propertyDescriptor) { + IrPropertyImpl(propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, it) + }.also { + it.parent = propertyParent + propertyParent.addMember(it) + } + } irProperty.backingField = generatePropertyBackingField(propertyDescriptor, irProperty).apply { parent = propertyParent correspondingPropertySymbol = irProperty.symbol @@ -288,9 +306,12 @@ interface IrBuilderExtension { descriptor: PropertyAccessorDescriptor, fieldSymbol: IrFieldSymbol ): IrSimpleFunction { - val declaration = compilerContext.symbolTable.declareSimpleFunctionWithOverrides(fieldSymbol.owner.startOffset, - fieldSymbol.owner.endOffset, - SERIALIZABLE_PLUGIN_ORIGIN, descriptor) + val symbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor) + + val declaration = if (symbol.isBound) symbol.owner.also { generateOverriddenFunctionSymbols(it, compilerContext.symbolTable) } else compilerContext.symbolTable.declareSimpleFunctionWithOverrides(fieldSymbol.owner.startOffset, + fieldSymbol.owner.endOffset, + SERIALIZABLE_PLUGIN_ORIGIN, descriptor) + return declaration.buildWithScope { irAccessor -> irAccessor.createParameterDeclarations(receiver = null) irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType() @@ -496,15 +517,17 @@ interface IrBuilderExtension { nullableSerializerClass: IrClassSymbol ): IrExpression { return if (type.isMarkedNullable) { - val nullableConstructor = - compilerContext.symbolTable.referenceConstructor(nullableSerializerClass.descriptor.constructors.toList().first()) + val classDeclaration = nullableSerializerClass.owner + val nullableConstructor = classDeclaration.declarations.first { it is IrConstructor } as IrConstructor val resultType = type.makeNotNullable() + val typeParameters = classDeclaration.typeParameters + val typeArguments = listOf(resultType.toIrType()) irInvoke( - null, nullableConstructor, - typeArguments = listOf(resultType.toIrType()), + null, nullableConstructor.symbol, + typeArguments = typeArguments, valueArguments = listOf(expression), // Return type should be correctly substituted - returnTypeHint = nullableConstructor.descriptor.returnType.replace(listOf(resultType.asTypeProjection())).toIrType() + returnTypeHint = nullableConstructor.returnType.substitute(typeParameters, typeArguments) ) } else { expression @@ -663,7 +686,11 @@ interface IrBuilderExtension { compilerContext.symbolTable.referenceConstructor(serializerClass.unsubstitutedPrimaryConstructor!!) } // Return type should be correctly substituted - val substitutedReturnType = ctor.descriptor.returnType.replace(typeArgs.map { it.toKotlinType().asTypeProjection() }).toIrType() + val substitutedReturnType = if (ctor.isBound) { + val ctorDecl = ctor.owner + val typeParameters = ctorDecl.parentAsClass.typeParameters + ctor.owner.returnType.substitute(typeParameters, typeArgs) + } else ctor.descriptor.returnType.replace(typeArgs.map { it.toKotlinType().asTypeProjection() }).toIrType() return irInvoke(null, ctor, typeArguments = typeArgs, valueArguments = args, returnTypeHint = substitutedReturnType) } } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt index 95d95dd04f9..4b5bbd00e1b 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt @@ -60,10 +60,9 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil introduceValueParameter(thisAsReceiverParameter) prop = generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, desc, irClass) - irClass.addMember(prop) localSerializersFieldsDescriptors.forEach { - irClass.addMember(generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, it, irClass)) + generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, it, irClass) } } @@ -233,7 +232,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil // fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder val beginFunc = encoderClass.referenceMethod(CallingConventions.begin) { it.valueParameters.size == 1 } - val call = irCall(beginFunc, type = beginFunc.descriptor.returnType!!.toIrType()).mapValueParametersIndexed { _, _ -> + val call = irCall(beginFunc, type = beginFunc.owner.returnType).mapValueParametersIndexed { _, _ -> irGet(localSerialDesc) } // can it be done in more concise way? e.g. additional builder function?