diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt index 06dbd565241..e0814abeff1 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt @@ -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.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* 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 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 multiplied = irCallOp(context.irBuiltIns.intTimesSymbol, context.irBuiltIns.intType, propertyNameHashCode, irInt(127)) 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 // 2. Properties should be retrieved using getters without accessing backing fields // (DataClassMembersGenerator typically tries to access fields) + // 3. Custom equals function should be used on properties fun generateEqualsUsingGetters(equalsFun: IrSimpleFunction, typeForEquals: IrType, properties: List) = equalsFun.apply { body = backendContext.createIrBuilder(symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { val irType = typeForEquals @@ -245,7 +247,7 @@ class AnnotationImplementationMemberGenerator( for (property in properties) { val arg1 = property.get(irThis()) 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() } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DataClassMembersGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DataClassMembersGenerator.kt index 9dab16706f6..4730b687015 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DataClassMembersGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DataClassMembersGenerator.kt @@ -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( startOffset: Int = SYNTHETIC_OFFSET, endOffset: Int = SYNTHETIC_OFFSET, @@ -172,7 +175,7 @@ abstract class DataClassMembersGenerator( private fun getHashCodeOfProperty(property: IrProperty): IrExpression { return when { - property.backingField!!.type.isNullable() -> + property.type.isNullable() -> irIfNull( context.irBuiltIns.intType, irGetProperty(irThis(), property), @@ -195,7 +198,7 @@ abstract class DataClassMembersGenerator( val irPropertyValue = irGetProperty(irThis(), property) - val classifier = property.backingField!!.type.classifierOrNull + val classifier = property.type.classifierOrNull val irPropertyStringValue = if (classifier.isArrayOrPrimitiveArray) 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)) 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 { val hashCodeFunctionInfo = getHashCodeFunctionInfo(type) @@ -242,9 +245,6 @@ abstract class DataClassMembersGenerator( irPropertiesByDescriptor[property] ?: throw AssertionError("Class: ${irClass.descriptor}: unexpected property descriptor: $property") - fun getBackingField(property: PropertyDescriptor): IrField = - getIrProperty(property).backingField!! - val IrClassifierSymbol?.isArrayOrPrimitiveArray: Boolean get() = this == context.irBuiltIns.arrayClass || this in context.irBuiltIns.primitiveArraysToPrimitiveTypes diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeAnnotationImplementationTransformer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeAnnotationImplementationTransformer.kt index 7a8cbebf61a..ea4105f4b52 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeAnnotationImplementationTransformer.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeAnnotationImplementationTransformer.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer 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.expressions.* 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) { + require(!annotationClass.isFinalClass) { "Annotation class ${annotationClass.kotlinFqName} shouldn't be final" } val properties = annotationClass.getAnnotationProperties() properties.forEach { property -> val propType = property.getter!!.returnType