[Commonizer] Fallback for const val properties with different values

This commit is contained in:
Dmitriy Dolovov
2020-06-16 11:58:32 +07:00
parent ee455abe52
commit af1dd6251e
6 changed files with 71 additions and 27 deletions
@@ -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?
@@ -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?,
@@ -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<CirProperty>(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<CirProperty> = mutableListOf()
}
class ConstSameValue(val compileTimeInitializer: ConstantValue<*>) : Const()
class ConstMultipleValues(previous: ConstSameValue) : Const() {
init {
properties += previous.properties
}
}
}
}
@@ -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
@@ -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
@@ -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