[IR] Fixed bug with wrong init order of a enum's entries
This fixes https://youtrack.jetbrains.com/issue/KT-38540 (cherry picked from commit d031526a6e1a618597898dd6beadb04eed74b478)
This commit is contained in:
+19
-21
@@ -282,29 +282,27 @@ internal class EnumClassLowering(val context: Context) : FileLoweringPass {
|
|||||||
val valuesInitializer = irBuilder.irBlock(startOffset, endOffset) {
|
val valuesInitializer = irBuilder.irBlock(startOffset, endOffset) {
|
||||||
val receiver = implObject.thisReceiver!!
|
val receiver = implObject.thisReceiver!!
|
||||||
val instances = irTemporary(irGetField(irGet(receiver), loweredEnum.valuesField))
|
val instances = irTemporary(irGetField(irGet(receiver), loweredEnum.valuesField))
|
||||||
enumEntries
|
val enumIndices = enumEntries.sortedBy { it.name }.withIndex().associate { it.value to it.index }
|
||||||
.sortedBy { it.name }
|
enumEntries.forEach {
|
||||||
.withIndex()
|
val instance = irCall(arrayGetSymbol).apply {
|
||||||
.forEach {
|
dispatchReceiver = irGet(instances)
|
||||||
val instance = irCall(arrayGetSymbol).apply {
|
putValueArgument(0, irInt(enumIndices[it]!!))
|
||||||
dispatchReceiver = irGet(instances)
|
}
|
||||||
putValueArgument(0, irInt(it.index))
|
val initializer = it.initializerExpression!!.expression
|
||||||
}
|
initializer.setDeclarationsParent(constructor)
|
||||||
val initializer = it.value.initializerExpression!!.expression
|
when {
|
||||||
initializer.setDeclarationsParent(constructor)
|
initializer is IrConstructorCall -> +initInstanceCall(instance, initializer)
|
||||||
when {
|
|
||||||
initializer is IrConstructorCall -> +initInstanceCall(instance, initializer)
|
|
||||||
|
|
||||||
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> {
|
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> {
|
||||||
val statements = initializer.statements
|
val statements = initializer.statements
|
||||||
val constructorCall = statements.last() as IrConstructorCall
|
val constructorCall = statements.last() as IrConstructorCall
|
||||||
statements[statements.lastIndex] = initInstanceCall(instance, constructorCall)
|
statements[statements.lastIndex] = initInstanceCall(instance, constructorCall)
|
||||||
+initializer
|
+initializer
|
||||||
}
|
|
||||||
|
|
||||||
else -> error("Unexpected initializer: $initializer")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else -> error("Unexpected initializer: $initializer")
|
||||||
|
}
|
||||||
|
}
|
||||||
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
||||||
extensionReceiver = irGet(receiver)
|
extensionReceiver = irGet(receiver)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package codegen.enum.kt38540
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
public enum class Node(
|
||||||
|
public val external: Boolean,
|
||||||
|
public val dependsOn: Set<Node>,
|
||||||
|
public val required: Boolean
|
||||||
|
) {
|
||||||
|
A(
|
||||||
|
external = false,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
B(
|
||||||
|
external = false,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
C(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
D(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
E(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
F(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
G(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = false
|
||||||
|
),
|
||||||
|
H(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
I(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
J(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
K(
|
||||||
|
external = true,
|
||||||
|
dependsOn = setOf(I),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
L(
|
||||||
|
external = true,
|
||||||
|
dependsOn = setOf(I),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
M(
|
||||||
|
external = true,
|
||||||
|
dependsOn = setOf(I),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
N(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
O(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
AG(
|
||||||
|
external = true,
|
||||||
|
dependsOn = emptySet(),
|
||||||
|
required = true
|
||||||
|
),
|
||||||
|
FIELD_REPORT(
|
||||||
|
external = true,
|
||||||
|
dependsOn = setOf(AG, O, J),
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun runTest() {
|
||||||
|
assertTrue(Node.FIELD_REPORT.dependsOn.contains(Node.AG))
|
||||||
|
assertTrue(Node.FIELD_REPORT.dependsOn.contains(Node.O))
|
||||||
|
assertTrue(Node.FIELD_REPORT.dependsOn.contains(Node.J))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user