From af1dd6251ee6d5da42fbc96781a5026fbe750ece Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Tue, 16 Jun 2020 11:58:32 +0700 Subject: [PATCH] [Commonizer] Fallback for const val properties with different values --- .../descriptors/commonizer/cir/CirProperty.kt | 2 +- .../commonizer/cir/impl/CirPropertyImpl.kt | 2 +- .../commonizer/core/PropertyCommonizer.kt | 54 +++++++++++++++---- .../commonized/common/package_root.kt | 8 +++ .../commonized/js/package_root.kt | 16 +++--- .../commonized/jvm/package_root.kt | 16 +++--- 6 files changed, 71 insertions(+), 27 deletions(-) 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 6f0380a06e2..32b4c22cd0f 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 @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue interface CirProperty : CirFunctionOrProperty, CirLiftedUpDeclaration { val isVar: Boolean val isLateInit: Boolean - val isConst: Boolean + var isConst: Boolean val isDelegate: Boolean val getter: CirPropertyGetter? val setter: CirPropertySetter? 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 28fc2cd1b04..c67f5108cdd 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 @@ -25,7 +25,7 @@ data class CirPropertyImpl( override val kind: CallableMemberDescriptor.Kind, override val isVar: Boolean, override val isLateInit: Boolean, - override val isConst: Boolean, + override var isConst: Boolean, override val isDelegate: Boolean, override val getter: CirPropertyGetter?, override val setter: CirPropertySetter?, 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 64b76cc4c83..4712d2e2095 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 @@ -8,17 +8,25 @@ package org.jetbrains.kotlin.descriptors.commonizer.core 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.core.PropertyCommonizer.ConstCommonizationState.* 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 + private lateinit var constCommonizationState: ConstCommonizationState override fun commonizationResult(): CirProperty { val setter = setter.result - val constCompileTimeInitializer = constCompileTimeInitializer + + val constCommonizationState = constCommonizationState + val constCompileTimeInitializer = (constCommonizationState as? ConstSameValue)?.compileTimeInitializer + + if (constCommonizationState is ConstMultipleValues) { + // fix all commonized properties to make then non-const + constCommonizationState.properties.forEach { it.isConst = false } + } return CirPropertyFactory.create( annotations = emptyList(), @@ -46,8 +54,10 @@ class PropertyCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropert override fun initialize(first: CirProperty) { super.initialize(first) - if (first.isConst) { - constCompileTimeInitializer = first.compileTimeInitializer + constCommonizationState = if (first.isConst) { + first.compileTimeInitializer?.let(::ConstSameValue) ?: NonConst + } else { + NonConst } } @@ -57,16 +67,28 @@ class PropertyCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropert return false } - val constCompileTimeInitializer = constCompileTimeInitializer + val constCommonizationState = constCommonizationState 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 + when (constCommonizationState) { + NonConst -> { + // previous property was not constant + return false + } + is Const -> { + // previous property was constant + constCommonizationState.properties += next - if (constCompileTimeInitializer == null || constCompileTimeInitializer != next.compileTimeInitializer) { - // previous property was not constant or const properties have different constants - return false + if (constCommonizationState is ConstSameValue) { + if (constCommonizationState.compileTimeInitializer != next.compileTimeInitializer) { + // const properties have different constants + this.constCommonizationState = ConstMultipleValues(constCommonizationState) + } + } + } } - } else if (constCompileTimeInitializer != null) { + } else if (constCommonizationState != NonConst) { // previous property was constant but this one is not return false } @@ -80,4 +102,18 @@ class PropertyCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropert return result } + + private sealed class ConstCommonizationState { + object NonConst : ConstCommonizationState() + abstract class Const : ConstCommonizationState() { + val properties: MutableList = mutableListOf() + } + + class ConstSameValue(val compileTimeInitializer: ConstantValue<*>) : Const() + class ConstMultipleValues(previous: ConstSameValue) : Const() { + init { + properties += previous.properties + } + } + } } diff --git a/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/common/package_root.kt b/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/common/package_root.kt index 60c20a3626e..8d8236f1f09 100644 --- a/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/common/package_root.kt +++ b/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/common/package_root.kt @@ -2,10 +2,18 @@ const val property1 = 42 expect val property4: Int const val property5: Byte = 42 +expect val property6: Byte const val property7: Short = 42 +expect val property8: Short const val property9: Long = 42 +expect val property10: Long const val property11: Double = 4.2 +expect val property12: Double const val property13: Float = 4.2f +expect val property14: Float const val property15 = true +expect val property16: Boolean const val property17 = "42" +expect val property18: String const val property19: Char = 42.toChar() +expect val property20: Char diff --git a/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/js/package_root.kt b/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/js/package_root.kt index 7ae0ccd474d..a16585e9dbf 100644 --- a/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/js/package_root.kt +++ b/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/js/package_root.kt @@ -2,14 +2,14 @@ const val property2 = 42 val property3 = 42 // intentionally left as non-const actual val property4 = 42 -const val property6: Byte = 42 -const val property8: Short = 42 -const val property10: Long = 42 -const val property12: Double = 4.2 -const val property14: Float = 4.2f -const val property16 = true -const val property18 = "42" -const val property20: Char = 42.toChar() +actual val property6: Byte = 42 +actual val property8: Short = 42 +actual val property10: Long = 42 +actual val property12: Double = 4.2 +actual val property14: Float = 4.2f +actual val property16 = true +actual val property18 = "42" +actual val property20: Char = 42.toChar() const val property21: Byte = 42 const val property22: Short = 42 diff --git a/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/jvm/package_root.kt b/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/jvm/package_root.kt index c4a4d06d091..c2c40ded57b 100644 --- a/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/jvm/package_root.kt +++ b/native/commonizer/testData/propertyCommonization/liftingUpConst/commonized/jvm/package_root.kt @@ -2,14 +2,14 @@ val property2 = 42 // intentionally left as non-const const val property3 = 42 actual val property4 = 42 -const val property6: Byte = 142 -const val property8: Short = 142 -const val property10: Long = 142 -const val property12: Double = 14.2 -const val property14: Float = 14.2f -const val property16 = false -const val property18 = "142" -const val property20: Char = 142.toChar() +actual val property6: Byte = 142 +actual val property8: Short = 142 +actual val property10: Long = 142 +actual val property12: Double = 14.2 +actual val property14: Float = 14.2f +actual val property16 = false +actual val property18 = "142" +actual val property20: Char = 142.toChar() const val property21: Char = 42.toChar() const val property22: Byte = 42