diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index 700e0e37cdb..0d930508e93 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -89,6 +89,20 @@ internal class ClassMemberGenerator( else -> declaration.accept(visitor, null) } } + + if (klass is FirRegularClass && (irClass.isValue || irClass.isData)) { + val dataClassMembersGenerator = DataClassMembersGenerator(components) + if (irClass.isSingleFieldValueClass) { + dataClassMembersGenerator.generateBodiesForSingleFieldValueClassMembers(klass, irClass) + } + if (irClass.isMultiFieldValueClass) { + dataClassMembersGenerator.generateBodiesForMultiFieldValueClassMembers(klass, irClass) + } + if (irClass.isData) { + dataClassMembersGenerator.generateBodiesForDataClassMembers(klass, irClass) + } + } + annotationGenerator.generate(irClass, klass) if (irPrimaryConstructor != null) { declarationStorage.leaveScope(irPrimaryConstructor.symbol) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt index 675de048812..0b5c8f20946 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt @@ -56,17 +56,27 @@ import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components { fun generateSingleFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass): List { - return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER) - .generate(klass) + return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER).generateHeaders() + } + + fun generateBodiesForSingleFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass) { + MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER).generateBodies() } fun generateMultiFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass): List { - return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER) - .generate(klass) + return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER).generateHeaders() + } + + fun generateBodiesForMultiFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass) { + MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER).generateBodies() } fun generateDataClassMembers(klass: FirRegularClass, irClass: IrClass): List { - return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generate(klass) + return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generateHeaders() + } + + fun generateBodiesForDataClassMembers(klass: FirRegularClass, irClass: IrClass) { + MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generateBodies() } fun generateDataClassComponentBody(irFunction: IrFunction, klass: FirRegularClass) { @@ -179,12 +189,74 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon UNDEFINED_OFFSET ) - fun generate(klass: FirRegularClass): List { + fun generateHeaders(): List { + val result = mutableListOf() + val contributedSyntheticFunctions = calculateSyntheticFirFunctions() + + val toStringContributedFunction = contributedSyntheticFunctions[TO_STRING] + if (toStringContributedFunction != null) { + result.add(toStringContributedFunction) + val toStringFunction = createSyntheticIrFunction( + TO_STRING, + toStringContributedFunction, + components.irBuiltIns.stringType, + ) + irClass.declarations.add(toStringFunction) + } + + val hashcodeNameContributedFunction = contributedSyntheticFunctions[HASHCODE_NAME] + if (hashcodeNameContributedFunction != null) { + result.add(hashcodeNameContributedFunction) + val hashCodeFunction = createSyntheticIrFunction( + HASHCODE_NAME, + hashcodeNameContributedFunction, + components.irBuiltIns.intType, + ) + irClass.declarations.add(hashCodeFunction) + } + + val equalsContributedFunction = contributedSyntheticFunctions[EQUALS] + if (equalsContributedFunction != null) { + result.add(equalsContributedFunction) + val equalsFunction = createSyntheticIrFunction( + EQUALS, + equalsContributedFunction, + components.irBuiltIns.booleanType, + otherParameterNeeded = true, + isOperator = true + ) + irClass.declarations.add(equalsFunction) + } + + return result + } + + fun generateBodies() { val propertyParametersCount = irClass.primaryConstructor?.explicitParameters?.size ?: 0 val properties = irClass.properties.filter { it.backingField != null }.take(propertyParametersCount).toList() - val result = mutableListOf() + val contributedSyntheticFunctions = calculateSyntheticFirFunctions() + val toStringContributedFunction = contributedSyntheticFunctions[TO_STRING] + if (toStringContributedFunction != null) { + val toStringFunction = irClass.functions.first { it.name == TO_STRING && it.origin == origin } + irDataClassMembersGenerator.generateToStringMethod(toStringFunction, properties) + } + + val hashcodeNameContributedFunction = contributedSyntheticFunctions[HASHCODE_NAME] + if (hashcodeNameContributedFunction != null) { + val hashCodeFunction = irClass.functions.first { it.name == HASHCODE_NAME && it.origin == origin } + irDataClassMembersGenerator.generateHashCodeMethod(hashCodeFunction, properties) + } + + val equalsContributedFunction = contributedSyntheticFunctions[EQUALS] + if (equalsContributedFunction != null) { + val equalsFunction = irClass.functions.first { it.name == EQUALS && it.origin == origin } + irDataClassMembersGenerator.generateEqualsMethod(equalsFunction, properties) + } + } + + private fun calculateSyntheticFirFunctions(): Map { val scope = klass.unsubstitutedScope( components.session, components.scopeSession, @@ -206,46 +278,7 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon } } } - - val toStringContributedFunction = contributedSyntheticFunctions[TO_STRING] - if (toStringContributedFunction != null) { - result.add(toStringContributedFunction) - val toStringFunction = createSyntheticIrFunction( - TO_STRING, - toStringContributedFunction, - components.irBuiltIns.stringType, - ) - irDataClassMembersGenerator.generateToStringMethod(toStringFunction, properties) - irClass.declarations.add(toStringFunction) - } - - val hashcodeNameContributedFunction = contributedSyntheticFunctions[HASHCODE_NAME] - if (hashcodeNameContributedFunction != null) { - result.add(hashcodeNameContributedFunction) - val hashCodeFunction = createSyntheticIrFunction( - HASHCODE_NAME, - hashcodeNameContributedFunction, - components.irBuiltIns.intType, - ) - irDataClassMembersGenerator.generateHashCodeMethod(hashCodeFunction, properties) - irClass.declarations.add(hashCodeFunction) - } - - val equalsContributedFunction = contributedSyntheticFunctions[EQUALS] - if (equalsContributedFunction != null) { - result.add(equalsContributedFunction) - val equalsFunction = createSyntheticIrFunction( - EQUALS, - equalsContributedFunction, - components.irBuiltIns.booleanType, - otherParameterNeeded = true, - isOperator = true - ) - irDataClassMembersGenerator.generateEqualsMethod(equalsFunction, properties) - irClass.declarations.add(equalsFunction) - } - - return result + return contributedSyntheticFunctions } fun generateComponentBody(irFunction: IrFunction) { diff --git a/compiler/testData/codegen/box/ir/kt52677.kt b/compiler/testData/codegen/box/ir/kt52677.kt index 6ee4c1d2a97..ed829852f74 100644 --- a/compiler/testData/codegen/box/ir/kt52677.kt +++ b/compiler/testData/codegen/box/ir/kt52677.kt @@ -1,5 +1,4 @@ // ISSUE: KT-52677 -// IGNORE_BACKEND_K2: ANY // MODULE: lib // FILE: lib.kt diff --git a/compiler/testData/ir/irText/declarations/kt52677.fir.ir.txt b/compiler/testData/ir/irText/declarations/kt52677.fir.ir.txt index 75f6b835d87..58442d73d97 100644 --- a/compiler/testData/ir/irText/declarations/kt52677.fir.ir.txt +++ b/compiler/testData/ir/irText/declarations/kt52677.fir.ir.txt @@ -85,7 +85,7 @@ FILE fqName: fileName:/kt52677.kt $this: VALUE_PARAMETER name: type:.LoginSuccessPacket BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .LoginSuccessPacket' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null + CALL 'public open fun hashCode (): kotlin.Int declared in .Uuid1' type=kotlin.Int origin=null $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:id type:@[MySerializable(c = ...)] .Uuid1 visibility:private [final]' type=@[MySerializable(c = CLASS_REFERENCE 'CLASS OBJECT name:UuidSerializer modality:FINAL visibility:public superTypes:[.MySerializer<@[MySerializable(c = ...)] .Uuid1>]' type=kotlin.reflect.KClass<.UuidSerializer>)] .Uuid1 origin=null receiver: GET_VAR ': .LoginSuccessPacket declared in .LoginSuccessPacket.hashCode' type=.LoginSuccessPacket origin=null FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.LoginSuccessPacket, other:kotlin.Any?) returnType:kotlin.Boolean [operator]