Refactor DataClassMembersGenerator.kt for better work with LazyIr

^KT-49428
This commit is contained in:
Pavel Kunyavskiy
2021-10-27 11:46:04 +03:00
committed by Space
parent f4a88bde4e
commit d127815626
3 changed files with 13 additions and 9 deletions
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
@@ -221,16 +222,17 @@ class AnnotationImplementationMemberGenerator(
override fun IrBuilderWithScope.shiftResultOfHashCode(irResultVar: IrVariable): IrExpression = irGet(irResultVar) // no default (* 31) override fun IrBuilderWithScope.shiftResultOfHashCode(irResultVar: IrVariable): IrExpression = irGet(irResultVar) // no default (* 31)
override fun getHashCodeOf(builder: IrBuilderWithScope, property: IrProperty, irValue: IrExpression): IrExpression = with(builder) { override fun getHashCodeOf(builder: IrBuilderWithScope, property: IrProperty, irValue: IrExpression): IrExpression = with(builder) {
val propertyValueHashCode = getHashCodeOf(property.backingField!!.type, irValue) val propertyValueHashCode = getHashCodeOf(property.type, irValue)
val propertyNameHashCode = getHashCodeOf(backendContext.irBuiltIns.stringType, irString(property.name.toString())) val propertyNameHashCode = getHashCodeOf(backendContext.irBuiltIns.stringType, irString(property.name.toString()))
val multiplied = irCallOp(context.irBuiltIns.intTimesSymbol, context.irBuiltIns.intType, propertyNameHashCode, irInt(127)) val multiplied = irCallOp(context.irBuiltIns.intTimesSymbol, context.irBuiltIns.intType, propertyNameHashCode, irInt(127))
return irCallOp(context.irBuiltIns.intXorSymbol, context.irBuiltIns.intType, multiplied, propertyValueHashCode) return irCallOp(context.irBuiltIns.intXorSymbol, context.irBuiltIns.intType, multiplied, propertyValueHashCode)
} }
// Manual implementation of equals is required for two reasons: // Manual implementation of equals is required for following reasons:
// 1. `other` should be casted to interface instead of implementation // 1. `other` should be casted to interface instead of implementation
// 2. Properties should be retrieved using getters without accessing backing fields // 2. Properties should be retrieved using getters without accessing backing fields
// (DataClassMembersGenerator typically tries to access fields) // (DataClassMembersGenerator typically tries to access fields)
// 3. Custom equals function should be used on properties
fun generateEqualsUsingGetters(equalsFun: IrSimpleFunction, typeForEquals: IrType, properties: List<IrProperty>) = equalsFun.apply { fun generateEqualsUsingGetters(equalsFun: IrSimpleFunction, typeForEquals: IrType, properties: List<IrProperty>) = equalsFun.apply {
body = backendContext.createIrBuilder(symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { body = backendContext.createIrBuilder(symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
val irType = typeForEquals val irType = typeForEquals
@@ -245,7 +247,7 @@ class AnnotationImplementationMemberGenerator(
for (property in properties) { for (property in properties) {
val arg1 = property.get(irThis()) val arg1 = property.get(irThis())
val arg2 = property.get(irGet(irType, otherWithCast.symbol)) val arg2 = property.get(irGet(irType, otherWithCast.symbol))
+irIfThenReturnFalse(irNot(selectEquals(property.getter?.returnType ?: property.backingField!!.type, arg1, arg2))) +irIfThenReturnFalse(irNot(selectEquals(property.type, arg1, arg2)))
} }
+irReturnTrue() +irReturnTrue()
} }
@@ -48,6 +48,9 @@ abstract class DataClassMembersGenerator(
} }
} }
protected val IrProperty.type
get() = this.backingField?.type ?: this.getter?.returnType ?: error("Can't find type of ${this.render()}")
private inner class MemberFunctionBuilder( private inner class MemberFunctionBuilder(
startOffset: Int = SYNTHETIC_OFFSET, startOffset: Int = SYNTHETIC_OFFSET,
endOffset: Int = SYNTHETIC_OFFSET, endOffset: Int = SYNTHETIC_OFFSET,
@@ -172,7 +175,7 @@ abstract class DataClassMembersGenerator(
private fun getHashCodeOfProperty(property: IrProperty): IrExpression { private fun getHashCodeOfProperty(property: IrProperty): IrExpression {
return when { return when {
property.backingField!!.type.isNullable() -> property.type.isNullable() ->
irIfNull( irIfNull(
context.irBuiltIns.intType, context.irBuiltIns.intType,
irGetProperty(irThis(), property), irGetProperty(irThis(), property),
@@ -195,7 +198,7 @@ abstract class DataClassMembersGenerator(
val irPropertyValue = irGetProperty(irThis(), property) val irPropertyValue = irGetProperty(irThis(), property)
val classifier = property.backingField!!.type.classifierOrNull val classifier = property.type.classifierOrNull
val irPropertyStringValue = val irPropertyStringValue =
if (classifier.isArrayOrPrimitiveArray) if (classifier.isArrayOrPrimitiveArray)
irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol, context.irBuiltIns.stringType).apply { irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol, context.irBuiltIns.stringType).apply {
@@ -216,7 +219,7 @@ abstract class DataClassMembersGenerator(
irCallOp(context.irBuiltIns.intTimesSymbol, context.irBuiltIns.intType, irGet(irResultVar), irInt(31)) irCallOp(context.irBuiltIns.intTimesSymbol, context.irBuiltIns.intType, irGet(irResultVar), irInt(31))
protected open fun getHashCodeOf(builder: IrBuilderWithScope, property: IrProperty, irValue: IrExpression) = protected open fun getHashCodeOf(builder: IrBuilderWithScope, property: IrProperty, irValue: IrExpression) =
builder.getHashCodeOf(property.backingField!!.type, irValue) builder.getHashCodeOf(property.type, irValue)
protected fun IrBuilderWithScope.getHashCodeOf(type: IrType, irValue: IrExpression): IrExpression { protected fun IrBuilderWithScope.getHashCodeOf(type: IrType, irValue: IrExpression): IrExpression {
val hashCodeFunctionInfo = getHashCodeFunctionInfo(type) val hashCodeFunctionInfo = getHashCodeFunctionInfo(type)
@@ -242,9 +245,6 @@ abstract class DataClassMembersGenerator(
irPropertiesByDescriptor[property] irPropertiesByDescriptor[property]
?: throw AssertionError("Class: ${irClass.descriptor}: unexpected property descriptor: $property") ?: throw AssertionError("Class: ${irClass.descriptor}: unexpected property descriptor: $property")
fun getBackingField(property: PropertyDescriptor): IrField =
getIrProperty(property).backingField!!
val IrClassifierSymbol?.isArrayOrPrimitiveArray: Boolean val IrClassifierSymbol?.isArrayOrPrimitiveArray: Boolean
get() = this == context.irBuiltIns.arrayClass || this in context.irBuiltIns.primitiveArraysToPrimitiveTypes get() = this == context.irBuiltIns.arrayClass || this in context.irBuiltIns.primitiveArraysToPrimitiveTypes
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer
import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.ir.isFinalClass
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
@@ -35,6 +36,7 @@ internal class NativeAnnotationImplementationTransformer(context: Context, irFil
} }
override fun implementAnnotationPropertiesAndConstructor(implClass: IrClass, annotationClass: IrClass, generatedConstructor: IrConstructor) { override fun implementAnnotationPropertiesAndConstructor(implClass: IrClass, annotationClass: IrClass, generatedConstructor: IrConstructor) {
require(!annotationClass.isFinalClass) { "Annotation class ${annotationClass.kotlinFqName} shouldn't be final" }
val properties = annotationClass.getAnnotationProperties() val properties = annotationClass.getAnnotationProperties()
properties.forEach { property -> properties.forEach { property ->
val propType = property.getter!!.returnType val propType = property.getter!!.returnType