Fix creating of lazy delegated property in kotlinx.serialization

Fixes Kotlin/kotlinx.serialization#1616
This commit is contained in:
Sergey Shanshin
2021-08-02 16:27:03 +00:00
committed by Space
parent 4c3fb8697b
commit b42d6a3e85
3 changed files with 17 additions and 29 deletions

View File

@@ -10,15 +10,11 @@ import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.interpreter.toIrConst
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.*
@@ -42,7 +38,6 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.FUNCTION0_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.KPROPERTY1_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FUNC_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_MODE_FQ
@@ -129,24 +124,17 @@ interface IrBuilderExtension {
val publicationEntryDescriptor = lazySafeModeClassDescriptor.enumEntries().single { it.name == LAZY_PUBLICATION_MODE_NAME }
val lazyIrClass = compilerContext.referenceClass(LAZY_FQ)!!.owner
val lazyKotlinType = lazyIrClass.defaultType.substitute(mapOf(lazyIrClass.typeParameters[0].symbol to targetIrType)).toKotlinType()
val kPropertyIrClass = compilerContext.referenceClass(KPROPERTY1_FQ)!!.owner
val kPropertyKotlinType = kPropertyIrClass.defaultType.substitute(
mapOf(
kPropertyIrClass.typeParameters[0].symbol to targetIrType,
kPropertyIrClass.typeParameters[1].symbol to containingClass.defaultType,
)
).toKotlinType()
val targetKotlinType = targetIrType.toKotlinType()
val lazyIrType = lazyIrClass.defaultType.substitute(mapOf(lazyIrClass.typeParameters[0].symbol to targetIrType))
val propertyDescriptor =
KSerializerDescriptorResolver.createValPropertyDescriptor(name, containingClass.descriptor, targetKotlinType)
KSerializerDescriptorResolver.createValPropertyDescriptor(
Name.identifier(name.asString() + "\$delegate"),
containingClass.descriptor,
lazyIrType.toKotlinType(),
createGetter = true
)
val delegate = IrPropertyDelegateDescriptorImpl(propertyDescriptor, lazyKotlinType, kPropertyKotlinType)
return generateSimplePropertyWithBackingField(delegate, containingClass, delegate.name).apply {
return generateSimplePropertyWithBackingField(propertyDescriptor, containingClass).apply {
val builder = DeclarationIrBuilder(compilerContext, containingClass.symbol, startOffset, endOffset)
val initializerBody = builder.run {
val enumElement = IrGetEnumValueImpl(
@@ -159,7 +147,7 @@ interface IrBuilderExtension {
val lambdaExpression = containingClass.createLambdaExpression(targetIrType, initializerBuilder)
irExprBody(
irInvoke(null, lazyFunctionSymbol, listOf(targetIrType), listOf(enumElement, lambdaExpression), targetIrType)
irInvoke(null, lazyFunctionSymbol, listOf(targetIrType), listOf(enumElement, lambdaExpression), lazyIrType)
)
}
backingField!!.initializer = initializerBody
@@ -196,15 +184,16 @@ interface IrBuilderExtension {
}
}
fun IrBlockBodyBuilder.getLazyValueExpression(companionClass: IrClass, property: IrProperty): IrExpression {
fun IrBlockBodyBuilder.getLazyValueExpression(thisParam: IrValueParameter, property: IrProperty, type: IrType): IrExpression {
val lazyIrClass = compilerContext.referenceClass(LAZY_FQ)!!.owner
val valueGetter = lazyIrClass.getPropertyGetter("value")!!
val backingField = property.backingField!!
return irGet(
backingField.type,
irGetField(irGetObject(companionClass), backingField),
valueGetter
val propertyGetter = property.getter!!
return irInvoke(
irGet(propertyGetter.returnType, irGet(thisParam), propertyGetter.symbol),
valueGetter,
typeHint = type
)
}

View File

@@ -122,7 +122,7 @@ class SerializableCompanionIrGenerator(
}
irClass.contributeFunction(methodDescriptor) {
+irReturn(getLazyValueExpression(irClass, property))
+irReturn(getLazyValueExpression(it.dispatchReceiverParameter!!, property, targetIrType))
}
generateSerializerFactoryIfNeeded(methodDescriptor)
}

View File

@@ -139,7 +139,6 @@ internal object SerializationDependencies {
val LAZY_FQ = FqName("kotlin.Lazy")
val LAZY_FUNC_FQ = FqName("kotlin.lazy")
val LAZY_MODE_FQ = FqName("kotlin.LazyThreadSafetyMode")
val KPROPERTY1_FQ = FqName("kotlin.reflect.KProperty1")
val FUNCTION0_FQ = FqName("kotlin.Function0")
val LAZY_PUBLICATION_MODE_NAME = Name.identifier("PUBLICATION")
}