[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 receiver = implObject.thisReceiver!!
|
||||
val instances = irTemporary(irGetField(irGet(receiver), loweredEnum.valuesField))
|
||||
enumEntries
|
||||
.sortedBy { it.name }
|
||||
.withIndex()
|
||||
.forEach {
|
||||
val instance = irCall(arrayGetSymbol).apply {
|
||||
dispatchReceiver = irGet(instances)
|
||||
putValueArgument(0, irInt(it.index))
|
||||
}
|
||||
val initializer = it.value.initializerExpression!!.expression
|
||||
initializer.setDeclarationsParent(constructor)
|
||||
when {
|
||||
initializer is IrConstructorCall -> +initInstanceCall(instance, initializer)
|
||||
val enumIndices = enumEntries.sortedBy { it.name }.withIndex().associate { it.value to it.index }
|
||||
enumEntries.forEach {
|
||||
val instance = irCall(arrayGetSymbol).apply {
|
||||
dispatchReceiver = irGet(instances)
|
||||
putValueArgument(0, irInt(enumIndices[it]!!))
|
||||
}
|
||||
val initializer = it.initializerExpression!!.expression
|
||||
initializer.setDeclarationsParent(constructor)
|
||||
when {
|
||||
initializer is IrConstructorCall -> +initInstanceCall(instance, initializer)
|
||||
|
||||
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> {
|
||||
val statements = initializer.statements
|
||||
val constructorCall = statements.last() as IrConstructorCall
|
||||
statements[statements.lastIndex] = initInstanceCall(instance, constructorCall)
|
||||
+initializer
|
||||
}
|
||||
|
||||
else -> error("Unexpected initializer: $initializer")
|
||||
}
|
||||
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> {
|
||||
val statements = initializer.statements
|
||||
val constructorCall = statements.last() as IrConstructorCall
|
||||
statements[statements.lastIndex] = initInstanceCall(instance, constructorCall)
|
||||
+initializer
|
||||
}
|
||||
|
||||
else -> error("Unexpected initializer: $initializer")
|
||||
}
|
||||
}
|
||||
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
||||
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