From 2ce16259893c878194f9ebb02bb3d213ab8d9014 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Wed, 27 May 2020 13:38:59 +0700 Subject: [PATCH] [Commonizer] Lift up identical const properties ^KMM-241 --- .../commonizer/builder/propertyDescriptors.kt | 12 +++++-- .../commonizer/cir/CirDeclaration.kt | 8 +++++ .../descriptors/commonizer/cir/CirProperty.kt | 2 +- .../cir/factory/CirPropertyFactory.kt | 9 +++-- .../commonizer/cir/impl/CirPropertyImpl.kt | 3 +- .../commonizer/core/PropertyCommonizer.kt | 36 ++++++++++++++++--- 6 files changed, 57 insertions(+), 13 deletions(-) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt index 5c85348c1f1..60cb766c814 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt @@ -24,10 +24,16 @@ internal fun CirPropertyNode.buildDescriptors( containingDeclarations: List ) { val commonProperty = common() - val markAsExpectAndActual = commonProperty != null && commonProperty.kind != CallableMemberDescriptor.Kind.SYNTHESIZED - target.forEachIndexed { index, property -> - property?.buildDescriptor(components, output, index, containingDeclarations, isActual = markAsExpectAndActual) + val isLiftedUp = commonProperty?.isLiftedUp == true + val markAsExpectAndActual = commonProperty != null + && commonProperty.kind != CallableMemberDescriptor.Kind.SYNTHESIZED + && !isLiftedUp + + if (!isLiftedUp) { + target.forEachIndexed { index, property -> + property?.buildDescriptor(components, output, index, containingDeclarations, isActual = markAsExpectAndActual) + } } commonProperty?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirDeclaration.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirDeclaration.kt index 01df59134b6..88ba4b2f550 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirDeclaration.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirDeclaration.kt @@ -53,5 +53,13 @@ interface CirCallableMemberWithParameters { val hasSynthesizedParameterNames: Boolean } +/** + * Indicates a declaration that could be completely lifted up to "common" fragment. + * NOTE: Interning can't be applied to the whole lifted declaration, only to its parts! + */ +interface CirLiftedUpDeclaration : CirDeclaration { + val isLiftedUp: Boolean +} + /** Indicates presence of recursion in lazy calculations. */ interface CirRecursionMarker : CirDeclaration diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirProperty.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirProperty.kt index 1473dc044ce..6f0380a06e2 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirProperty.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirProperty.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir import org.jetbrains.kotlin.resolve.constants.ConstantValue -interface CirProperty : CirFunctionOrProperty { +interface CirProperty : CirFunctionOrProperty, CirLiftedUpDeclaration { val isVar: Boolean val isLateInit: Boolean val isConst: Boolean diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirPropertyFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirPropertyFactory.kt index 6d4f212c8b8..cf49919a7db 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirPropertyFactory.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirPropertyFactory.kt @@ -51,7 +51,8 @@ object CirPropertyFactory { setter = source.setter?.let(CirPropertySetterFactory::create), backingFieldAnnotations = source.backingField?.annotations?.map(CirAnnotationFactory::create), delegateFieldAnnotations = source.delegateField?.annotations?.map(CirAnnotationFactory::create), - compileTimeInitializer = source.compileTimeInitializer + compileTimeInitializer = source.compileTimeInitializer, + isLiftedUp = false ) } @@ -75,7 +76,8 @@ object CirPropertyFactory { setter: CirPropertySetter?, backingFieldAnnotations: List?, delegateFieldAnnotations: List?, - compileTimeInitializer: ConstantValue<*>? + compileTimeInitializer: ConstantValue<*>?, + isLiftedUp: Boolean ): CirProperty { return CirPropertyImpl( annotations = annotations, @@ -96,7 +98,8 @@ object CirPropertyFactory { setter = setter, backingFieldAnnotations = backingFieldAnnotations, delegateFieldAnnotations = delegateFieldAnnotations, - compileTimeInitializer = compileTimeInitializer + compileTimeInitializer = compileTimeInitializer, + isLiftedUp = isLiftedUp ) } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirPropertyImpl.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirPropertyImpl.kt index 67ae0c945ca..c7029886fa4 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirPropertyImpl.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirPropertyImpl.kt @@ -31,5 +31,6 @@ data class CirPropertyImpl( override val setter: CirPropertySetter?, override val backingFieldAnnotations: List?, override val delegateFieldAnnotations: List?, - override val compileTimeInitializer: ConstantValue<*>? + override val compileTimeInitializer: ConstantValue<*>?, + override val isLiftedUp: Boolean ) : CirProperty diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/PropertyCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/PropertyCommonizer.kt index 91d063a6df9..099c920518f 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/PropertyCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/PropertyCommonizer.kt @@ -9,13 +9,16 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirProperty import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirPropertyFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirPropertyGetterFactory import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache +import org.jetbrains.kotlin.resolve.constants.ConstantValue class PropertyCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropertyCommonizer(cache) { private val setter = PropertySetterCommonizer() private var isExternal = true + private var constCompileTimeInitializer: ConstantValue<*>? = null override fun commonizationResult(): CirProperty { val setter = setter.result + val constCompileTimeInitializer = constCompileTimeInitializer return CirPropertyFactory.create( annotations = emptyList(), @@ -30,20 +33,43 @@ class PropertyCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropert kind = kind, isVar = setter != null, isLateInit = false, - isConst = false, + isConst = constCompileTimeInitializer != null, isDelegate = false, getter = CirPropertyGetterFactory.DEFAULT_NO_ANNOTATIONS, setter = setter, backingFieldAnnotations = null, delegateFieldAnnotations = null, - compileTimeInitializer = null + compileTimeInitializer = constCompileTimeInitializer, + isLiftedUp = constCompileTimeInitializer != null ) } + override fun initialize(first: CirProperty) { + super.initialize(first) + + if (first.isConst) { + constCompileTimeInitializer = first.compileTimeInitializer + } + } + override fun doCommonizeWith(next: CirProperty): Boolean { - when { - next.isConst -> return false // expect property can't be const because expect can't have initializer - next.isLateInit -> return false // expect property can't be lateinit + if (next.isLateInit) { + // expect property can't be lateinit + return false + } + + val constCompileTimeInitializer = constCompileTimeInitializer + if (next.isConst) { + // const properties should be lifted up + // otherwise commonization should fail: expect property can't be const because expect can't have initializer + + if (constCompileTimeInitializer == null || constCompileTimeInitializer != next.compileTimeInitializer) { + // previous property was not constant or const properties have different constants + return false + } + } else if (constCompileTimeInitializer != null) { + // previous property was constant but this one is not + return false } val result = super.doCommonizeWith(next)