[K2] Don't crash compiler if receiver on property wasn't evaluated
Compilation crash must be handled separately in `convertToConstantValues` method because we still want successfully compile common code. All constants will be evaluated later on fir2ir phase. #KT-59362 Fixed
This commit is contained in:
+19
-16
@@ -48,6 +48,8 @@ internal data class FirToConstantValueTransformerData(
|
|||||||
val constValueProvider: ConstValueProvider?,
|
val constValueProvider: ConstValueProvider?,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val constantIntrinsicCalls = setOf("toByte", "toLong", "toShort", "toFloat", "toDouble", "toChar", "unaryMinus")
|
||||||
|
|
||||||
internal abstract class FirToConstantValueTransformer(
|
internal abstract class FirToConstantValueTransformer(
|
||||||
private val failOnNonConst: Boolean,
|
private val failOnNonConst: Boolean,
|
||||||
) : FirDefaultVisitor<ConstantValue<*>?, FirToConstantValueTransformerData>() {
|
) : FirDefaultVisitor<ConstantValue<*>?, FirToConstantValueTransformerData>() {
|
||||||
@@ -162,22 +164,25 @@ internal abstract class FirToConstantValueTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
symbol.callableId.packageName.asString() == "kotlin" -> {
|
symbol.callableId.packageName.asString() == "kotlin" -> {
|
||||||
|
val callableName = symbol.callableId.callableName.asString()
|
||||||
|
if (callableName !in constantIntrinsicCalls) return null
|
||||||
|
|
||||||
val dispatchReceiver = qualifiedAccessExpression.dispatchReceiver
|
val dispatchReceiver = qualifiedAccessExpression.dispatchReceiver
|
||||||
val dispatchReceiverValue by lazy { dispatchReceiver.toConstantValue(data) }
|
val dispatchReceiverValue = dispatchReceiver.toConstantValue(data) ?: return null
|
||||||
when (symbol.callableId.callableName.asString()) {
|
when (callableName) {
|
||||||
"toByte" -> ByteValue((dispatchReceiverValue!!.value as Number).toByte())
|
"toByte" -> ByteValue((dispatchReceiverValue.value as Number).toByte())
|
||||||
"toLong" -> LongValue((dispatchReceiverValue!!.value as Number).toLong())
|
"toLong" -> LongValue((dispatchReceiverValue.value as Number).toLong())
|
||||||
"toShort" -> ShortValue((dispatchReceiverValue!!.value as Number).toShort())
|
"toShort" -> ShortValue((dispatchReceiverValue.value as Number).toShort())
|
||||||
"toFloat" -> FloatValue((dispatchReceiverValue!!.value as Number).toFloat())
|
"toFloat" -> FloatValue((dispatchReceiverValue.value as Number).toFloat())
|
||||||
"toDouble" -> DoubleValue((dispatchReceiverValue!!.value as Number).toDouble())
|
"toDouble" -> DoubleValue((dispatchReceiverValue.value as Number).toDouble())
|
||||||
"toChar" -> CharValue((dispatchReceiverValue!!.value as Number).toInt().toChar())
|
"toChar" -> CharValue((dispatchReceiverValue.value as Number).toInt().toChar())
|
||||||
"unaryMinus" -> {
|
"unaryMinus" -> {
|
||||||
when (val receiverValue = dispatchReceiverValue) {
|
when (dispatchReceiverValue) {
|
||||||
is ByteValue -> ByteValue((-receiverValue.value).toByte())
|
is ByteValue -> ByteValue((-dispatchReceiverValue.value).toByte())
|
||||||
is LongValue -> LongValue(-receiverValue.value)
|
is LongValue -> LongValue(-dispatchReceiverValue.value)
|
||||||
is ShortValue -> ShortValue((-receiverValue.value).toShort())
|
is ShortValue -> ShortValue((-dispatchReceiverValue.value).toShort())
|
||||||
is FloatValue -> FloatValue(-receiverValue.value)
|
is FloatValue -> FloatValue(-dispatchReceiverValue.value)
|
||||||
is DoubleValue -> DoubleValue(-receiverValue.value)
|
is DoubleValue -> DoubleValue(-dispatchReceiverValue.value)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,8 +240,6 @@ internal object FirToConstantValueChecker : FirDefaultVisitor<Boolean, FirSessio
|
|||||||
ConstantValueKind.Int, ConstantValueKind.UnsignedInt, ConstantValueKind.Long, ConstantValueKind.UnsignedLong,
|
ConstantValueKind.Int, ConstantValueKind.UnsignedInt, ConstantValueKind.Long, ConstantValueKind.UnsignedLong,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val constantIntrinsicCalls = setOf("toByte", "toLong", "toShort", "toFloat", "toDouble", "toChar", "unaryMinus")
|
|
||||||
|
|
||||||
override fun visitElement(element: FirElement, data: FirSession): Boolean {
|
override fun visitElement(element: FirElement, data: FirSession): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -4,4 +4,6 @@ $TESTDATA_DIR$/kt58139/platform.kt
|
|||||||
-language-version
|
-language-version
|
||||||
2.0
|
2.0
|
||||||
-d
|
-d
|
||||||
$TEMP_DIR$
|
$TEMP_DIR$
|
||||||
|
-cp
|
||||||
|
$TESTDATA_DIR$/../../../../dist/common/kotlin-stdlib-common.jar
|
||||||
@@ -6,3 +6,4 @@ annotation class AnnKlass(val arg: String)
|
|||||||
fun foo() {}
|
fun foo() {}
|
||||||
|
|
||||||
const val BATCH_SIZE: Int = 16 * 1024
|
const val BATCH_SIZE: Int = 16 * 1024
|
||||||
|
const val REPLACEMENT_BYTE: Byte = '?'.code.toByte()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const val DOUBLE_BATCH_SIZE = 2 * BATCH_SIZE
|
const val DOUBLE_BATCH_SIZE = 2 * BATCH_SIZE
|
||||||
|
const val REPLACEMENT_BYTE_AS_INT = REPLACEMENT_BYTE.toInt()
|
||||||
|
|
||||||
annotation class A(val value: Int)
|
annotation class A(val value: Int)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user