From 406bc4e4976dbd100abfa20b86377a9f4e0dc01a Mon Sep 17 00:00:00 2001 From: "Evgeniy.Zhelenskiy" Date: Wed, 11 May 2022 20:13:26 +0300 Subject: [PATCH] [IR] Fix compilation of MFVC in different module #KT-1179 --- .../lower/JvmMultiFieldValueClassLowering.kt | 17 +++-------------- ...emoizedMultiFieldValueClassReplacements.kt | 19 +++++++++++-------- ...ultiFieldValueClassSpecificDeclarations.kt | 17 +++++++++++------ 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt index 8cd2a01f6e9..bdef9e21748 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt @@ -64,7 +64,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV fun remapSymbol(original: IrValueSymbol, replacement: IrValueDeclaration) { symbol2getter[original] = { irGet(replacement) } - symbol2setters[original] = listOf(if (replacement.isAssignable) { _, value -> irSet(replacement, value) } else null) + symbol2setters[original] = if (replacement.isAssignable) listOf { _, value -> irSet(replacement, value) } else listOf(null) } fun remapSymbol( @@ -262,7 +262,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV } override fun handleSpecificNewClass(declaration: IrClass) { - replacements.setOldFields(declaration, declaration.fields.toList()) + replacements.commitMFVCOldProperties(declaration) val newDeclarations = replacements.getDeclarations(declaration)!! if (newDeclarations.valueClass != declaration) error("Unexpected IrClass ${newDeclarations.valueClass} instead of $declaration") newDeclarations.replaceFields() @@ -317,17 +317,11 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV private fun MultiFieldValueClassSpecificDeclarations.replaceFields() { valueClass.declarations.removeIf { it is IrField } valueClass.declarations += fields - for (field in fields) { - field.parent = valueClass - } } private fun MultiFieldValueClassSpecificDeclarations.replaceProperties() { valueClass.declarations.removeAll(oldProperties.values.mapNotNull { it.getter }) - properties.values.forEach { - it.parent = valueClass - } - valueClass.declarations += properties.values.map { it.getter!!.apply { parent = valueClass } } + valueClass.declarations += properties.values.map { it.getter!! } } override fun createBridgeDeclaration(source: IrSimpleFunction, replacement: IrSimpleFunction, mangledName: Name): IrSimpleFunction = @@ -454,9 +448,6 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV fun MultiFieldValueClassSpecificDeclarations.buildPrimaryMultiFieldValueClassConstructor() { valueClass.declarations.removeIf { it is IrConstructor && it.isPrimary } val primaryConstructorReplacements = listOf(primaryConstructor, primaryConstructorImpl) - for (exConstructor in primaryConstructorReplacements) { - exConstructor.parent = valueClass - } valueClass.declarations += primaryConstructorReplacements val initializersStatements = valueClass.declarations.filterIsInstance().flatMap { it.body.statements } @@ -483,7 +474,6 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV }) } valueClass.declarations += boxMethod - boxMethod.parent = valueClass } fun MultiFieldValueClassSpecificDeclarations.buildUnboxFunctions() { @@ -493,7 +483,6 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV @Suppress("unused") fun MultiFieldValueClassSpecificDeclarations.buildSpecializedEqualsMethod() { // todo defaults - specializedEqualsMethod.parent = valueClass specializedEqualsMethod.body = with(context.createIrBuilder(specializedEqualsMethod.symbol)) { // TODO: Revisit this once we allow user defined equals methods in inline/multi-field value classes. leaves.indices.map { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt index d2606fe77e6..73bcfb88ac7 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt @@ -44,14 +44,16 @@ class MemoizedMultiFieldValueClassReplacements( null } - private val oldFields: MutableMap> = - ConcurrentHashMap>().withDefault { it.fields.toList() } - - fun setOldFields(irClass: IrClass, fields: List) { - oldFields[irClass] = fields + val getOldMFVCProperties: (IrClass) -> List = storageManager.createMemoizedFunction { irClass -> + require(irClass.isMultiFieldValueClass) { "No need to save data for non MFVC" } + (irClass.properties.toList().filter { it.getter?.isMultiFieldValueClassOriginalFieldGetter == true }.takeIf { it.isNotEmpty() } + ?: irClass.fields.mapNotNull { it.correspondingPropertySymbol?.owner }.toList().takeIf { it.isNotEmpty() } + ?: error("No properties found: ${irClass.render()}")) } - fun getOldFields(irClass: IrClass): List = oldFields.getOrPut(irClass) { irClass.fields.toList() } + fun commitMFVCOldProperties(irClass: IrClass) { + getOldMFVCProperties(irClass) + } class ValueParameterTemplate( val name: String, @@ -258,8 +260,9 @@ class MemoizedMultiFieldValueClassReplacements( } function is IrSimpleFunction && !function.isFromJava() && function.fullValueParameterList.any { it.type.isMultiFieldValueClassType() && !it.type.isNullable() } && - !(function.isFakeOverride && - bindingOldFunctionToParameterTemplateStructure[findSuperDeclaration(function, false, context.state.jvmDefaultMode)] == null)-> + (!function.isFakeOverride || + findSuperDeclaration(function, false, context.state.jvmDefaultMode) + in bindingOldFunctionToParameterTemplateStructure) -> createMethodReplacement(function) else -> null } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MultiFieldValueClassSpecificDeclarations.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MultiFieldValueClassSpecificDeclarations.kt index 245f00ee699..fc22c39b6fe 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MultiFieldValueClassSpecificDeclarations.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MultiFieldValueClassSpecificDeclarations.kt @@ -77,14 +77,14 @@ sealed class MultiFieldValueClassTree { ) : this(type, defaultInternalNodeValue, 0.let { val valueClassRepresentation = type.erasedUpperBound.valueClassRepresentation as MultiFieldValueClassRepresentation val primaryConstructor = type.erasedUpperBound.primaryConstructor!! - val fieldsByName = replacements.getOldFields(primaryConstructor.constructedClass).associateBy { it.name } + val propertiesByName = replacements.getOldMFVCProperties(primaryConstructor.constructedClass).associateBy { it.name } valueClassRepresentation.underlyingPropertyNamesToTypes.map { (name, type) -> - val field = fieldsByName[name]!! - val innerVisibility = field.correspondingPropertySymbol!!.owner.visibility + val property = propertiesByName[name]!! + val innerVisibility = property.visibility val comparison = visibility.compareTo(innerVisibility) ?: error("Expected comparable visibilities but got $visibility and $innerVisibility") val newVisibility = if (comparison < 0) visibility else innerVisibility - TreeField(name, type, defaultInternalNodeValue, newVisibility, field.annotations, defaultLeafValue, replacements) + TreeField(name, type, defaultInternalNodeValue, newVisibility, property.annotations, defaultLeafValue, replacements) } }) @@ -223,15 +223,16 @@ class MultiFieldValueClassSpecificDeclarations( } val oldPrimaryConstructor = valueClass.primaryConstructor ?: error("Value classes have primary constructors") - private val oldFields = replacements.getOldFields(valueClass) - val oldProperties = oldFields.map { it.correspondingPropertySymbol!!.owner }.associateBy { it.name } + val oldProperties = replacements.getOldMFVCProperties(valueClass).associateBy { it.name } val fields = leaves.map { leaf -> irFactory.buildField { this.name = nodeFullNames[leaf]!! this.type = leaf.type visibility = DescriptorVisibilities.PRIVATE + }.apply { + parent = valueClass } } @@ -300,6 +301,7 @@ class MultiFieldValueClassSpecificDeclarations( copyTypeParametersFrom(oldPrimaryConstructor) addFlattenedClassRepresentationToParameters() val irConstructor = this@apply + parent = valueClass body = context.createIrBuilder(irConstructor.symbol).irBlockBody(irConstructor) { +irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single()) for (i in leaves.indices) { @@ -319,6 +321,7 @@ class MultiFieldValueClassSpecificDeclarations( returnType = context.irBuiltIns.unitType modality = Modality.FINAL }.apply { + parent = valueClass copyTypeParametersFrom(oldPrimaryConstructor) addFlattenedClassRepresentationToParameters() // body is added in Lowering file @@ -329,6 +332,7 @@ class MultiFieldValueClassSpecificDeclarations( origin = JvmLoweredDeclarationOrigin.SYNTHETIC_MULTI_FIELD_VALUE_CLASS_MEMBER returnType = valueClass.defaultType }.apply { + parent = valueClass copyTypeParametersFrom(valueClass) addFlattenedClassRepresentationToParameters() // body is added in Lowering file @@ -349,6 +353,7 @@ class MultiFieldValueClassSpecificDeclarations( origin = JvmLoweredDeclarationOrigin.MULTI_FIELD_VALUE_CLASS_GENERATED_IMPL_METHOD returnType = context.irBuiltIns.booleanType }.apply { + parent = valueClass copyTypeParametersFrom(oldPrimaryConstructor) for (leaf in leaves) { addValueParameter {