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 ad1d1035d7b..872e3fcfa12 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 @@ -11,29 +11,19 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection -import org.jetbrains.kotlin.ir.types.makeNotNull -import org.jetbrains.kotlin.ir.types.toKotlinType -import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration -import org.jetbrains.kotlin.psi2ir.generators.DeclarationGenerator -import org.jetbrains.kotlin.psi2ir.generators.FunctionGenerator -import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext -import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound @@ -48,53 +38,11 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.* interface IrBuilderExtension { val compilerContext: SerializationPluginContext - private fun IrClass.declareSimpleFunctionWithExternalOverrides(descriptor: FunctionDescriptor): IrSimpleFunction { + fun IrClass.contributeFunction(descriptor: FunctionDescriptor, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) { 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) { - return FunctionGenerator( - DeclarationGenerator( - GeneratorContext( - Psi2IrConfiguration(), - moduleDescriptor, - bindingContext, - languageVersionSettings, - symbolTable, - GeneratorExtensions(), - typeTranslator, - typeTranslator.constantValueGenerator, - irBuiltIns - ) - ) - ) - } - - fun IrClass.contributeFunction( - descriptor: FunctionDescriptor, - bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit - ) { - val f: IrSimpleFunction = declareSimpleFunctionWithExternalOverrides(descriptor) - f.buildWithScope { - createFunctionGenerator().generateFunctionParameterDeclarationsAndReturnType(f, null, null) - } - + assert(functionSymbol.isBound) + val f: IrSimpleFunction = functionSymbol.owner + // TODO: default parameters f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody( this.startOffset, this.endOffset @@ -108,27 +56,10 @@ interface IrBuilderExtension { bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit ) { 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) - } - } + assert(ctorSymbol.isBound) + + val c = ctorSymbol.owner - c.returnType = descriptor.returnType.toIrType() - 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 @@ -141,7 +72,8 @@ interface IrBuilderExtension { vararg args: IrExpression, typeHint: IrType? = null ): IrMemberAccessExpression { - val returnType = typeHint ?: callee.run { if (isBound) owner.returnType else descriptor.returnType!!.toIrType() } + assert(callee.isBound) { "Symbol $callee expected to be bound" } + val returnType = typeHint ?: callee.run { owner.returnType } val call = irCall(callee, type = returnType) call.dispatchReceiver = dispatchReceiver args.forEachIndexed(call::putValueArgument) @@ -167,7 +99,7 @@ interface IrBuilderExtension { arrayElements: List ): IrExpression { - val arrayType = compilerContext.symbols.array.typeWith(arrayElementType) + val arrayType = compilerContext.irBuiltIns.arrayClass.typeWith(arrayElementType) val arg0 = IrVarargImpl(startOffset, endOffset, arrayType, arrayElementType, arrayElements) val typeArguments = listOf(arrayElementType) @@ -203,7 +135,7 @@ interface IrBuilderExtension { fun T.buildWithScope(builder: (T) -> Unit): T = also { irDeclaration -> - compilerContext.symbolTable.withScope(irDeclaration.descriptor) { + compilerContext.symbolTable.withReferenceScope(irDeclaration.descriptor) { builder(irDeclaration) } } @@ -253,12 +185,12 @@ interface IrBuilderExtension { */ fun IrBuilderWithScope.generateAnySuperConstructorCall(toBuilder: IrBlockBodyBuilder) { - val anyConstructor = compilerContext.builtIns.any.constructors.single() + val anyConstructor = compilerContext.irBuiltIns.anyClass.owner.declarations.single { it is IrConstructor } as IrConstructor with(toBuilder) { +IrDelegatingConstructorCallImpl( startOffset, endOffset, compilerContext.irBuiltIns.unitType, - compilerContext.symbolTable.referenceConstructor(anyConstructor) + anyConstructor.symbol ) } } @@ -266,26 +198,29 @@ interface IrBuilderExtension { fun generateSimplePropertyWithBackingField( ownerSymbol: IrValueSymbol, propertyDescriptor: PropertyDescriptor, - propertyParent: IrClass + propertyParent: IrClass, + declare: Boolean ): IrProperty { - 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 { + val irPropertySymbol = compilerContext.symbolTable.referenceProperty(propertyDescriptor) + assert(irPropertySymbol.isBound || declare) + + if (declare) { + IrPropertyImpl(propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, irPropertySymbol).also { it.parent = propertyParent propertyParent.addMember(it) } } + val irProperty = irPropertySymbol.owner + irProperty.backingField = generatePropertyBackingField(propertyDescriptor, irProperty).apply { parent = propertyParent - correspondingPropertySymbol = irProperty.symbol + correspondingPropertySymbol = irPropertySymbol } val fieldSymbol = irProperty.backingField!!.symbol - irProperty.getter = propertyDescriptor.getter?.let { generatePropertyAccessor(it, fieldSymbol) } - ?.apply { parent = propertyParent; correspondingPropertySymbol = irProperty.symbol } - irProperty.setter = propertyDescriptor.setter?.let { generatePropertyAccessor(it, fieldSymbol) } - ?.apply { parent = propertyParent; correspondingPropertySymbol = irProperty.symbol } + irProperty.getter = propertyDescriptor.getter?.let { generatePropertyAccessor(it, fieldSymbol, declare) } + ?.apply { parent = propertyParent } + irProperty.setter = propertyDescriptor.setter?.let { generatePropertyAccessor(it, fieldSymbol, declare) } + ?.apply { parent = propertyParent } return irProperty } @@ -293,34 +228,47 @@ interface IrBuilderExtension { propertyDescriptor: PropertyDescriptor, originProperty: IrProperty ): IrField { - return compilerContext.symbolTable.declareField( - originProperty.startOffset, - originProperty.endOffset, - SERIALIZABLE_PLUGIN_ORIGIN, - propertyDescriptor, - propertyDescriptor.type.toIrType() - ) + val fieldSymbol = compilerContext.symbolTable.referenceField(propertyDescriptor) + + if (fieldSymbol.isBound) return fieldSymbol.owner + + return originProperty.run { + // TODO: type parameters + IrFieldImpl(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, fieldSymbol, propertyDescriptor.type.toIrType()) + } } fun generatePropertyAccessor( descriptor: PropertyAccessorDescriptor, - fieldSymbol: IrFieldSymbol + fieldSymbol: IrFieldSymbol, + declare: Boolean ): IrSimpleFunction { val symbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor) + assert(symbol.isBound || declare) - val declaration = if (symbol.isBound) symbol.owner.also { generateOverriddenFunctionSymbols(it, compilerContext.symbolTable) } else compilerContext.symbolTable.declareSimpleFunctionWithOverrides(fieldSymbol.owner.startOffset, + if (declare) { + IrFunctionImpl( + fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, - SERIALIZABLE_PLUGIN_ORIGIN, descriptor) - - return declaration.buildWithScope { irAccessor -> - irAccessor.createParameterDeclarations(receiver = null) - irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType() - irAccessor.body = when (descriptor) { - is PropertyGetterDescriptor -> generateDefaultGetterBody(descriptor, irAccessor) - is PropertySetterDescriptor -> generateDefaultSetterBody(descriptor, irAccessor) - else -> throw AssertionError("Should be getter or setter: $descriptor") + SERIALIZABLE_PLUGIN_ORIGIN, + symbol, + descriptor.returnType!!.toIrType() + ).also { f -> + generateOverriddenFunctionSymbols(f, compilerContext.symbolTable) + f.createParameterDeclarations(receiver = null) + f.returnType = descriptor.returnType!!.toIrType() + f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol } } + + val irAccessor = symbol.owner + irAccessor.body = when (descriptor) { + is PropertyGetterDescriptor -> generateDefaultGetterBody(descriptor, irAccessor) + is PropertySetterDescriptor -> generateDefaultSetterBody(descriptor, irAccessor) + else -> throw AssertionError("Should be getter or setter: $descriptor") + } + + return irAccessor } private fun generateDefaultGetterBody( @@ -328,6 +276,7 @@ interface IrBuilderExtension { irAccessor: IrSimpleFunction ): IrBlockBody { val property = getter.correspondingProperty + val irProperty = irAccessor.correspondingPropertySymbol?.owner ?: error("Expected property for $getter") val startOffset = irAccessor.startOffset val endOffset = irAccessor.endOffset @@ -341,7 +290,7 @@ interface IrBuilderExtension { irAccessor.symbol, IrGetFieldImpl( startOffset, endOffset, - compilerContext.symbolTable.referenceField(property), + irProperty.backingField?.symbol ?: error("Property expected to have backing field"), property.type.toIrType(), receiver ) @@ -355,7 +304,7 @@ interface IrBuilderExtension { irAccessor: IrSimpleFunction ): IrBlockBody { val property = setter.correspondingProperty - + val irProperty = irAccessor.correspondingPropertySymbol?.owner ?: error("Expected corresponding property for accessor $setter") val startOffset = irAccessor.startOffset val endOffset = irAccessor.endOffset val irBody = IrBlockBodyImpl(startOffset, endOffset) @@ -366,7 +315,7 @@ interface IrBuilderExtension { irBody.statements.add( IrSetFieldImpl( startOffset, endOffset, - compilerContext.symbolTable.referenceField(property), + irProperty.backingField?.symbol ?: error("Property $property expected to have backing field"), receiver, IrGetValueImpl(startOffset, endOffset, irValueParameter.type, irValueParameter.symbol), compilerContext.irBuiltIns.unitType @@ -405,6 +354,11 @@ interface IrBuilderExtension { it.parent = this@createParameterDeclarations } + if (copyTypeParameters) { + assert(typeParameters.isEmpty()) + copyTypeParamsFromDescriptor() + } + dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter() extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter() @@ -412,22 +366,24 @@ interface IrBuilderExtension { assert(valueParameters.isEmpty()) valueParameters = descriptor.valueParameters.map { it.irValueParameter() } - - assert(typeParameters.isEmpty()) - if (copyTypeParameters) copyTypeParamsFromDescriptor() } fun IrFunction.copyTypeParamsFromDescriptor() { - typeParameters += descriptor.typeParameters.map { + val newTypeParameters = descriptor.typeParameters.map { IrTypeParameterImpl( startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, it ).also { typeParameter -> typeParameter.parent = this - typeParameter.superTypes.addAll(it.upperBounds.map { it.toIrType() }) } } + + newTypeParameters.forEach { typeParameter -> + typeParameter.superTypes.addAll(typeParameter.descriptor.upperBounds.map { it.toIrType() }) + } + + typeParameters = newTypeParameters } fun kClassTypeFor(projection: TypeProjection): SimpleType { @@ -443,7 +399,7 @@ interface IrBuilderExtension { startOffset, endOffset, returnType.toIrType(), - compilerContext.symbolTable.referenceClassifier(clazz), + compilerContext.referenceClass(clazz.fqNameSafe) ?: error("Couldn't load class $clazz"), classType.toIrType() ) } @@ -471,9 +427,10 @@ interface IrBuilderExtension { fun findEnumValuesMethod(enumClass: ClassDescriptor): IrFunction { assert(enumClass.kind == ClassKind.ENUM_CLASS) - return compilerContext.symbolTable.referenceClass(enumClass).owner.functions - .find { it.origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER && it.name == Name.identifier("values") } - ?: throw AssertionError("Enum class does not have .values() function") + return compilerContext.referenceClass(enumClass.fqNameSafe)?.let { + it.owner.functions.find { it.origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER && it.name == Name.identifier("values") } + ?: throw AssertionError("Enum class does not have .values() function") + } ?: error("Couldn't load class $enumClass") } private fun getEnumMembersNames(enumClass: ClassDescriptor): Sequence { @@ -490,8 +447,8 @@ interface IrBuilderExtension { dispatchReceiverParameter: IrValueParameter, property: SerializableProperty ): IrExpression? { - val nullableSerClass = - compilerContext.symbolTable.referenceClass(property.module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer)) + val nullableSerializerFqn = getInternalPackageFqn(SpecialBuiltins.nullableSerializer) + val nullableSerClass = compilerContext.referenceClass(nullableSerializerFqn) ?: error("Couldn't find class $nullableSerializerFqn") val serializer = property.serializableWith?.toClassDescriptor ?: if (!property.type.isTypeParameter()) generator.findTypeSerializerOrContext( @@ -517,15 +474,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 @@ -534,8 +493,8 @@ interface IrBuilderExtension { fun wrapIrTypeIntoKSerializerIrType(module: ModuleDescriptor, type: IrType, variance: Variance = Variance.INVARIANT): IrType { - val kSerClass = - compilerContext.symbolTable.referenceClass(module.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS)) + val serializerFqn = getSerializationPackageFqn(SerialEntityNames.KSERIALIZER_CLASS) + val kSerClass = compilerContext.referenceClass(serializerFqn) ?: error("Couldn't find class $serializerFqn") return IrSimpleTypeImpl( kSerClass, hasQuestionMark = false, arguments = listOf( makeTypeProjection(type, variance) @@ -569,8 +528,8 @@ interface IrBuilderExtension { genericIndex: Int? = null, genericGetter: ((Int, KotlinType) -> IrExpression)? = null ): IrExpression? { - val nullableSerClass = - compilerContext.symbolTable.referenceClass(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer)) + val nullableClassFqn = getInternalPackageFqn(SpecialBuiltins.nullableSerializer) + val nullableSerClass = compilerContext.referenceClass(nullableClassFqn) ?: error("Expecting class $nullableClassFqn") if (serializerClassOriginal == null) { if (genericIndex == null) return null return genericGetter?.invoke(genericIndex, kType) @@ -679,20 +638,48 @@ interface IrBuilderExtension { requireNotNull( findSerializerConstructorForTypeArgumentsSerializers(serializerClass) ) { "Generated serializer does not have constructor with required number of arguments" } - .let { compilerContext.symbolTable.referenceConstructor(it) } } else { - compilerContext.symbolTable.referenceConstructor(serializerClass.unsubstitutedPrimaryConstructor!!) + compilerContext.referenceConstructors(serializerClass.fqNameSafe).single { it.owner.isPrimary } } // Return type should be correctly substituted - 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() + assert(ctor.isBound) + val ctorDecl = ctor.owner + val typeParameters = ctorDecl.parentAsClass.typeParameters + val substitutedReturnType = ctorDecl.returnType.substitute(typeParameters, typeArgs) return irInvoke(null, ctor, typeArguments = typeArgs, valueArguments = args, returnTypeHint = substitutedReturnType) } } - fun ReferenceSymbolTable.serializableSyntheticConstructor(forClass: ClassDescriptor): IrConstructorSymbol = - referenceConstructor(forClass.constructors.single { it.isSerializationCtor() }) -} + private fun findSerializerConstructorForTypeArgumentsSerializers(serializer: ClassDescriptor): IrConstructorSymbol? { + val serializableImplementationTypeArguments = extractKSerializerArgumentFromImplementation(serializer)?.arguments + ?: throw AssertionError("Serializer does not implement KSerializer??") + + val typeParamsCount = serializableImplementationTypeArguments.size + if (typeParamsCount == 0) return null //don't need it + val constructors = compilerContext.referenceConstructors(serializer.fqNameSafe) + + fun isKSerializer(type: IrType): Boolean { + val simpleType = type as? IrSimpleType ?: return false + val classifier = simpleType.classifier as? IrClassSymbol ?: return false + return classifier.owner.fqNameWhenAvailable == SerialEntityNames.KSERIALIZER_NAME_FQ + } + + return constructors.singleOrNull { + it.owner.valueParameters.let { vps -> vps.size == typeParamsCount && vps.all { vp -> isKSerializer(vp.type) } } + } + } + + private fun IrConstructor.isSerializationCtor(): Boolean { + val serialMarker = + compilerContext.referenceClass(SerializationPackages.packageFqName.child(SerialEntityNames.SERIAL_CTOR_MARKER_NAME)) + + return valueParameters.lastOrNull()?.run { + name == SerialEntityNames.dummyParamName && type.classifierOrNull == serialMarker + } == true + } + + fun serializableSyntheticConstructor(forClass: IrClass): IrConstructorSymbol { + return forClass.declarations.filterIsInstance().single { it.isSerializationCtor() }.symbol + } + +} \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt index b6579c8b057..1c451bd6e72 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt @@ -12,19 +12,17 @@ import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irInt import org.jetbrains.kotlin.ir.builders.irReturn import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl -import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.patchDeclarationParents -import org.jetbrains.kotlin.ir.util.referenceFunction import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module -import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext @@ -63,16 +61,13 @@ class SerializableCompanionIrGenerator( ) ) ?: return - val irSerializableClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).takeIf { it.isBound }?.owner ?: return + val irSerializableClass = compilerContext.referenceClass(serializableDescriptor.fqNameSafe)?.owner ?: return val serializableWithAlreadyPresent = irSerializableClass.annotations.any { it.symbol.descriptor.constructedClass.fqNameSafe == annotationMarkerClass.fqNameSafe } if (serializableWithAlreadyPresent) return - val annotationCtor = requireNotNull(annotationMarkerClass.unsubstitutedPrimaryConstructor?.let { - compilerContext.symbolTable.referenceConstructor(it) - }) - + val annotationCtor = compilerContext.referenceConstructors(annotationMarkerClass.fqNameSafe).single { it.owner.isPrimary } val annotationType = annotationMarkerClass.defaultType.toIrType() val annotationCtorCall = IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, annotationType, annotationCtor).apply { val serializerType = serializer.toSimpleType(false) @@ -124,12 +119,11 @@ class SerializableCompanionIrGenerator( val kSerializerStarType = factory.returnType val array = factory.valueParameters.first() val argsSize = serializableDescriptor.declaredTypeParameters.size - val arrayGet = - compilerContext.builtIns.array.getFuncDesc("get").single() - val arrayGetSymbol = compilerContext.symbolTable.referenceFunction(arrayGet) + val arrayGet = compilerContext.irBuiltIns.arrayClass.owner.declarations.filterIsInstance() + .single { it.name.asString() == "get" } val serializers: List = (0 until argsSize).map { - irInvoke(irGet(array), arrayGetSymbol, irInt(it), typeHint = kSerializerStarType) + irInvoke(irGet(array), arrayGet.symbol, irInt(it), typeHint = kSerializerStarType) } val serializerCall = compilerContext.symbolTable.referenceSimpleFunction(getterDescriptor) val call = irInvoke( 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 539b29b80a1..eb4de352671 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 @@ -1,30 +1,22 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir -import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.lower.irThrow -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.CompilationException import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrProperty -import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrTypeProjection import org.jetbrains.kotlin.ir.types.classOrNull -import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.TypeTranslator +import org.jetbrains.kotlin.ir.util.getAnnotation import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless @@ -38,26 +30,42 @@ class SerializableIrGenerator( bindingContext: BindingContext ) : SerializableCodegen(irClass.descriptor, bindingContext), IrBuilderExtension { + private fun IrClass.getSuperClassOrAny(): IrClass { + val superClasses = superTypes.mapNotNull { it.classOrNull }.map { it.owner } + + return superClasses.singleOrNull { it.kind == ClassKind.CLASS } ?: compilerContext.irBuiltIns.anyClass.owner + } + + private fun IrClass.hasSerializableAnnotationWithoutArgs(): Boolean { + val annot = getAnnotation(SerializationAnnotations.serializableAnnotationFqName) ?: return false + + for (i in 0 until annot.valueArgumentsCount) { + if (annot.getValueArgument(i) != null) return false + } + + return true + } + + private val IrClass.isInternalSerializable: Boolean get() = kind == ClassKind.CLASS && hasSerializableAnnotationWithoutArgs() + override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) = - irClass.contributeConstructor(constructorDescriptor, overwriteValueParameters = true) { ctor -> + irClass.contributeConstructor(constructorDescriptor) { ctor -> val transformFieldInitializer = buildInitializersRemapping(irClass) // Missing field exception parts - val exceptionCtor = - serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC) - .unsubstitutedPrimaryConstructor!! - val exceptionCtorRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor) - val exceptionType = exceptionCtor.returnType.toIrType() + val exceptionFqn = getSerializationPackageFqn(MISSING_FIELD_EXC) + val exceptionCtorRef = compilerContext.referenceConstructors(exceptionFqn).single { it.owner.isPrimary } + val exceptionType = exceptionCtorRef.owner.returnType val serializableProperties = properties.serializableProperties val seenVarsOffset = serializableProperties.bitMaskSlotCount() val seenVars = (0 until seenVarsOffset).map { ctor.valueParameters[it] } val thiz = irClass.thisReceiver!! - val superClass = irClass.descriptor.getSuperClassOrAny() + val superClass = irClass.getSuperClassOrAny() var startPropOffset: Int = 0 when { - KotlinBuiltIns.isAny(superClass) -> generateAnySuperConstructorCall(toBuilder = this@contributeConstructor) + superClass.symbol == compilerContext.irBuiltIns.anyClass -> generateAnySuperConstructorCall(toBuilder = this@contributeConstructor) superClass.isInternalSerializable -> { startPropOffset = generateSuperSerializableCall(superClass, ctor.valueParameters, seenVarsOffset) } @@ -108,22 +116,23 @@ class SerializableIrGenerator( } } - private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: ClassDescriptor) { - val suitableCtor = superClass.constructors.singleOrNull { it.valueParameters.size == 0 } - ?: throw IllegalArgumentException("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor") - val ctorRef = compilerContext.symbolTable.referenceConstructor(suitableCtor) + private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: IrClass) { + val ctorRef = superClass.declarations.filterIsInstance().singleOrNull { it.valueParameters.isEmpty() } + ?: error("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor") + + val call = IrDelegatingConstructorCallImpl( startOffset, endOffset, compilerContext.irBuiltIns.unitType, - ctorRef + ctorRef.symbol ) call.insertTypeArgumentsForSuperClass(superClass) +call } - private fun IrDelegatingConstructorCallImpl.insertTypeArgumentsForSuperClass(superClass: ClassDescriptor) { - val superTypeCallArguments = (irClass.superTypes.find { it.classOrNull?.descriptor == superClass } as? IrSimpleType)?.arguments + private fun IrDelegatingConstructorCallImpl.insertTypeArgumentsForSuperClass(superClass: IrClass) { + val superTypeCallArguments = (irClass.superTypes.find { it.classOrNull == superClass.symbol } as IrSimpleType?)?.arguments superTypeCallArguments?.forEachIndexed { index, irTypeArgument -> val argType = irTypeArgument as? IrTypeProjection ?: throw IllegalStateException("Star projection in immediate argument for supertype") @@ -133,13 +142,13 @@ class SerializableIrGenerator( // returns offset in serializable properties array private fun IrBlockBodyBuilder.generateSuperSerializableCall( - superClass: ClassDescriptor, + superClass: IrClass, allValueParameters: List, propertiesStart: Int ): Int { check(superClass.isInternalSerializable) - val superCtorRef = compilerContext.symbolTable.serializableSyntheticConstructor(superClass) - val superProperties = bindingContext.serializablePropertiesFor(superClass).serializableProperties + val superCtorRef = serializableSyntheticConstructor(superClass) + val superProperties = bindingContext.serializablePropertiesFor(superClass.descriptor).serializableProperties val superSlots = superProperties.bitMaskSlotCount() val arguments = allValueParameters.subList(0, superSlots) + allValueParameters.subList(propertiesStart, propertiesStart + superProperties.size) + diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt index fdf855a769f..d8b11a50877 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt @@ -9,10 +9,13 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.isSubtypeOfClass import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.properties @@ -20,6 +23,7 @@ import org.jetbrains.kotlin.ir.util.referenceFunction import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext import org.jetbrains.kotlinx.serialization.compiler.resolve.* @@ -35,7 +39,7 @@ class SerializerForEnumsGenerator( IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol) val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS) - val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(anySerialDescProperty?.getter!!) + val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol val encodeEnum = encoderClass.referenceMethod(CallingConventions.encodeEnum) val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol) @@ -51,7 +55,7 @@ class SerializerForEnumsGenerator( IrGetValueImpl(startOffset, endOffset, loadFunc.dispatchReceiverParameter!!.symbol) val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS) - val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(anySerialDescProperty?.getter!!) + val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol val decode = decoderClass.referenceMethod(CallingConventions.decodeEnum) val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol) @@ -59,13 +63,14 @@ class SerializerForEnumsGenerator( val valuesF = serializableIrClass.functions.single { it.name == DescriptorUtils.ENUM_VALUES } val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol) - val arrayGet = - compilerContext.builtIns.array.getFuncDesc("get").single() - val arrayGetSymbol = compilerContext.symbolTable.referenceFunction(arrayGet) + + val arrayGet = compilerContext.irBuiltIns.arrayClass.owner.declarations.filterIsInstance() + .single { it.name.asString() == "get" } + val getValueByOrdinal = irInvoke( getValues, - arrayGetSymbol, + arrayGet.symbol, irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter), typeHint = serializableIrClass.defaultType ) @@ -78,8 +83,7 @@ class SerializerForEnumsGenerator( ): IrExpression { val serialDescForEnums = serializerDescriptor .getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_FOR_ENUM) - val ctor = - compilerContext.symbolTable.referenceConstructor(serialDescForEnums.unsubstitutedPrimaryConstructor!!) + val ctor = compilerContext.referenceConstructors(serialDescForEnums.fqNameSafe).single { it.owner.isPrimary } return irInvoke( null, ctor, irString(serialName), 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 29abba9074f..3102ebe4d7a 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 @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrAnonymousInitializerImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl @@ -19,12 +20,11 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.constructors -import org.jetbrains.kotlin.ir.util.patchDeclarationParents -import org.jetbrains.kotlin.ir.util.referenceFunction -import org.jetbrains.kotlin.ir.util.withScope +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen @@ -43,7 +43,10 @@ object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER") open class SerializerIrGenerator(val irClass: IrClass, final override val compilerContext: SerializationPluginContext, bindingContext: BindingContext) : SerializerCodegen(irClass.descriptor, bindingContext), IrBuilderExtension { - protected val serializableIrClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).takeIf { it.isBound }?.owner + + protected val serializableIrClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).owner + protected val irAnySerialDescProperty = anySerialDescProperty?.let { compilerContext.symbolTable.referenceProperty(it) } + override fun generateSerialDesc() { val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return @@ -56,23 +59,26 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil lateinit var prop: IrProperty // how to (auto)create backing field and getter/setter? - compilerContext.symbolTable.withScope(irClass.descriptor) { + compilerContext.symbolTable.withReferenceScope(irClass.descriptor) { - introduceValueParameter(thisAsReceiverParameter) - prop = generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, desc, irClass) + prop = generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, desc, irClass, false) + // TODO: Do not use descriptors here localSerializersFieldsDescriptors.forEach { - generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, it, irClass) + generateSimplePropertyWithBackingField(thisAsReceiverParameter.symbol, it, irClass, true) } } - compilerContext.symbolTable.declareAnonymousInitializer( - irClass.startOffset, irClass.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, irClass.descriptor - ).buildWithScope { initIrBody -> - initIrBody.parent = irClass - val ctor = irClass.declarations.filterIsInstance().find { it.isPrimary } - ?: throw AssertionError("Serializer must have primary constructor") - compilerContext.symbolTable.withScope(initIrBody.descriptor) { + val annonimousInit = irClass.run { + val symbol = IrAnonymousInitializerSymbolImpl(descriptor) + IrAnonymousInitializerImpl(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, symbol).also { + it.parent = this + declarations.add(it) + } + } + + annonimousInit.buildWithScope { initIrBody -> + compilerContext.symbolTable.withReferenceScope(initIrBody.descriptor) { initIrBody.body = DeclarationIrBuilder(compilerContext, initIrBody.symbol, initIrBody.startOffset, initIrBody.endOffset).irBlockBody { val localDesc = irTemporary( @@ -83,7 +89,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS) // add class annotations copySerialInfoAnnotationsToDescriptor( - serializableIrClass?.annotations.orEmpty(), + serializableIrClass.annotations, localDesc, serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation) ) @@ -98,7 +104,6 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil irGet(localDesc) ) } - (ctor.body as? IrBlockBody)?.statements?.addAll(initIrBody.body.statements) } } } @@ -107,9 +112,8 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil serialDescImplClass: ClassDescriptor, correctThis: IrExpression ): IrExpression { - val serialDescImplConstructor = serialDescImplClass - .unsubstitutedPrimaryConstructor!! - val serialClassDescImplCtor = compilerContext.symbolTable.referenceConstructor(serialDescImplConstructor) + val classConstructors = compilerContext.referenceConstructors(serialDescImplClass.fqNameSafe) + val serialClassDescImplCtor = classConstructors.single { it.owner.isPrimary } return irInvoke( null, serialClassDescImplCtor, irString(serialName), if (isGeneratedSerializer) correctThis else irNull(), irInt(serializableProperties.size) @@ -209,15 +213,16 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil /* Already implemented in .generateSerialClassDesc ? */ } - protected inline fun ClassDescriptor.referenceMethod(methodName: String, predicate: (FunctionDescriptor) -> Boolean = { true }) = - getFuncDesc(methodName).single(predicate).let { compilerContext.symbolTable.referenceFunction(it) } + protected inline fun ClassDescriptor.referenceMethod(methodName: String, predicate: (IrSimpleFunction) -> Boolean = { true }): IrFunctionSymbol { + val irClass = compilerContext.referenceClass(fqNameSafe)?.owner ?: error("Couldn't load class $this") + val simpleFunctions = irClass.declarations.filterIsInstance() + return simpleFunctions.filter { it.name.asString() == methodName }.single { predicate(it) }.symbol + } override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc -> val fieldInitializer: (SerializableProperty) -> IrExpression? = - buildInitializersRemapping( - serializableIrClass ?: error("Please provide implementation of .deserialize method for external class") - ).run { { invoke(it.irField) } } + buildInitializersRemapping(serializableIrClass).run { { invoke(it.irField) } } fun irThis(): IrExpression = IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol) @@ -225,7 +230,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(STRUCTURE_ENCODER_CLASS) val encoderClass = serializerDescriptor.getClassFromSerializationPackage(ENCODER_CLASS) - val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(anySerialDescProperty?.getter!!) //??? + val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc") @@ -337,7 +342,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil val inputClass = serializerDescriptor.getClassFromSerializationPackage(STRUCTURE_DECODER_CLASS) val decoderClass = serializerDescriptor.getClassFromSerializationPackage(DECODER_CLASS) - val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(anySerialDescProperty?.getter!!) //??? + val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc") // workaround due to unavailability of labels (KT-25386) @@ -430,10 +435,9 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil decoderCalls.forEach { (i, e) -> +IrBranchImpl(irEquals(indexVar.get(), irInt(i)), e) } // throw exception on unknown field - val exceptionCtor = - serializableDescriptor.getClassFromSerializationPackage(UNKNOWN_FIELD_EXC) - .unsubstitutedPrimaryConstructor!! - val excClassRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor) + + val exceptionFqn = getSerializationPackageFqn(UNKNOWN_FIELD_EXC) + val excClassRef = compilerContext.referenceConstructors(exceptionFqn).single { it.owner.isPrimary } +elseBranch( irThrow( irInvoke( @@ -462,9 +466,9 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil val typeArgs = (loadFunc.returnType as IrSimpleType).arguments.map { (it as IrTypeProjection).type } val ctor: IrConstructorSymbol = if (serializableDescriptor.isInternalSerializable) { args = bitMasks.map { irGet(it) } + args + irNull() - compilerContext.symbolTable.serializableSyntheticConstructor(serializableDescriptor) + serializableSyntheticConstructor(serializableIrClass) } else { - compilerContext.symbolTable.referenceConstructor(serializableDescriptor.unsubstitutedPrimaryConstructor!!) + compilerContext.referenceConstructors(serializableDescriptor.fqNameSafe).single { it.owner.isPrimary } } +irReturn(irInvoke(null, ctor, typeArgs, args)) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SearchUtils.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SearchUtils.kt index 9ac3bd99fc7..948a28bcc10 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SearchUtils.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/SearchUtils.kt @@ -63,9 +63,15 @@ internal fun Annotations.findAnnotationKotlinTypeValue( internal fun ClassDescriptor.getKSerializerConstructorMarker(): ClassDescriptor = module.findClassAcrossModuleDependencies(ClassId(SerializationPackages.packageFqName, SerialEntityNames.SERIAL_CTOR_MARKER_NAME))!! +internal fun getInternalPackageFqn(classSimpleName: String): FqName = + SerializationPackages.internalPackageFqName.child(Name.identifier(classSimpleName)) + internal fun ModuleDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) = getFromPackage(SerializationPackages.internalPackageFqName, classSimpleName) +internal fun getSerializationPackageFqn(classSimpleName: String): FqName = + SerializationPackages.packageFqName.child(Name.identifier(classSimpleName)) + internal fun ModuleDescriptor.getClassFromSerializationPackage(classSimpleName: String) = getFromPackage(SerializationPackages.packageFqName, classSimpleName)