Fix enum interpretation in case when primary constructor is missing
This commit is contained in:
committed by
TeamCityServer
parent
668bb4fd71
commit
96cc74a752
@@ -415,15 +415,19 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
callInterceptor.interceptEnumEntry(enumEntry) {
|
||||
val enumClass = enumEntry.symbol.owner.parentAsClass
|
||||
val enumEntries = enumClass.declarations.filterIsInstance<IrEnumEntry>()
|
||||
val enumSuperCall = (enumClass.primaryConstructor?.body?.statements?.firstOrNull() as? IrEnumConstructorCall)
|
||||
val enumInitializer = enumEntry.initializerExpression?.expression
|
||||
?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
|
||||
val enumConstructorCall = enumInitializer as? IrEnumConstructorCall
|
||||
?: (enumInitializer as IrBlock).statements.filterIsInstance<IrEnumConstructorCall>().single()
|
||||
val enumSuperCall = enumConstructorCall.getSuperEnumCall()
|
||||
|
||||
val cleanEnumSuperCall = fun() {
|
||||
enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null
|
||||
enumSuperCall.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null
|
||||
callStack.popState() // result of constructor must be dropped, because next instruction will be `IrGetEnumValue`
|
||||
callStack.dropSubFrame()
|
||||
}
|
||||
|
||||
if (enumEntries.isNotEmpty() && enumSuperCall != null) {
|
||||
if (enumEntries.isNotEmpty()) {
|
||||
val valueArguments = listOf(
|
||||
enumEntry.name.asString().toIrConst(irBuiltIns.stringType),
|
||||
enumEntries.indexOf(enumEntry).toIrConst(irBuiltIns.intType)
|
||||
@@ -431,11 +435,6 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
valueArguments.forEachIndexed { index, irConst -> enumSuperCall.putValueArgument(index, irConst) }
|
||||
}
|
||||
|
||||
val enumInitializer = enumEntry.initializerExpression?.expression
|
||||
?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
|
||||
val enumConstructorCall = enumInitializer as? IrEnumConstructorCall
|
||||
?: (enumInitializer as IrBlock).statements.filterIsInstance<IrEnumConstructorCall>().single()
|
||||
|
||||
val enumClassObject = Variable(enumConstructorCall.getThisReceiver(), Common(enumEntry.correspondingClass ?: enumClass))
|
||||
environment.mapOfEnums[enumEntry.symbol] = enumClassObject.state as Complex
|
||||
|
||||
|
||||
@@ -269,4 +269,14 @@ internal fun IrType.getTypeIfReified(getType: (IrClassifierSymbol) -> IrType): I
|
||||
hasQuestionMark = this.hasQuestionMark || this@getTypeIfReified.hasQuestionMark
|
||||
arguments = newArguments
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrFunctionAccessExpression.getSuperEnumCall(): IrEnumConstructorCall {
|
||||
val name = this.symbol.owner.parentClassOrNull?.fqNameWhenAvailable?.asString()
|
||||
if (this is IrEnumConstructorCall && name == "kotlin.Enum") return this
|
||||
return when (val delegatingCall = this.symbol.owner.body?.statements?.get(0)) {
|
||||
is IrFunctionAccessExpression -> delegatingCall.getSuperEnumCall()
|
||||
is IrTypeOperatorCall -> (delegatingCall.argument as IrFunctionAccessExpression).getSuperEnumCall()
|
||||
else -> TODO("$delegatingCall is unexpected")
|
||||
}
|
||||
}
|
||||
+15
@@ -24,3 +24,18 @@ const val b3 = Color.RED.<!EVALUATED: `0xFF0000`!>getColorAsString()<!>
|
||||
|
||||
const val c1 = Color.BLACK.<!EVALUATED: `0`!>getColorAsInt()<!>
|
||||
const val c2 = Color.RED.<!EVALUATED: `16711680`!>getColorAsInt()<!>
|
||||
|
||||
@CompileTimeCalculation
|
||||
enum class EnumWithoutPrimary {
|
||||
X(), Y(10);
|
||||
|
||||
val someProp: Int
|
||||
|
||||
constructor() : this(0) {}
|
||||
constructor(value: Int) {
|
||||
someProp = value
|
||||
}
|
||||
}
|
||||
|
||||
const val d1 = EnumWithoutPrimary.X.<!EVALUATED: `0`!>someProp<!>
|
||||
const val d2 = EnumWithoutPrimary.Y.<!EVALUATED: `10`!>someProp<!>
|
||||
|
||||
Reference in New Issue
Block a user