JVM IR: Convert interface companion fields to static fields.

This commit is contained in:
Steven Schäfer
2019-08-07 14:19:17 +02:00
committed by max-kammerer
parent e6211c4995
commit f34a08cbbf
10 changed files with 22 additions and 20 deletions
@@ -69,21 +69,27 @@ private class MoveOrCopyCompanionObjectFieldsLowering(val context: CommonBackend
val companion = irClass.declarations.find {
it is IrClass && it.isCompanion
} as IrClass? ?: return
if ((irClass.isInterface || irClass.isAnnotationClass) && !companion.allFieldsAreJvmField()) return
companion.declarations.forEach {
// We don't move fields to interfaces unless all fields are annotated with @JvmField.
// It is an error to annotate only some of the fields of an interface companion with @JvmField.
val newParent = if (irClass.isJvmInterface && !companion.allFieldsAreJvmField()) companion else irClass
val newDeclarations = companion.declarations.mapNotNull {
when (it) {
is IrProperty -> {
val newField = movePropertyFieldToStaticParent(it, companion, irClass, fieldReplacementMap)
if (newField != null) irClass.declarations.add(newField)
}
is IrAnonymousInitializer -> {
val newInitializer = moveAnonymousInitializerToStaticParent(it, companion, irClass)
irClass.declarations.add(newInitializer)
}
else -> Unit
is IrProperty ->
movePropertyFieldToStaticParent(it, companion, newParent, fieldReplacementMap)
is IrAnonymousInitializer ->
moveAnonymousInitializerToStaticParent(it, companion, newParent)
else ->
null
}
}
companion.declarations.removeAll { it is IrAnonymousInitializer }
// Move declarations to parent if required
if (newParent !== companion) {
companion.declarations.removeAll { it is IrAnonymousInitializer }
newParent.declarations += newDeclarations
}
}
private fun copyConsts(irClass: IrClass) {
@@ -1,3 +1,7 @@
// IGNORE_BACKEND: JVM_IR
// Inside of the companion we have to access the instance through the local Companion field,
// not by indirection through the Companion field of the enclosing class.
// Class initialization might not have finished yet.
var result = ""
interface A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// Checks that accessor are not used because property can be accessed directly.
interface I {
@@ -1,5 +1,4 @@
// !LANGUAGE: +NoConstantValueAttributeForNonConstVals +JvmFieldInInterface
// IGNORE_BACKEND: JVM_IR
class C {
val testClassVal = 100
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.reflect.KProperty
class TestDelegate() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.reflect.KProperty
class TestDelegate() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
interface Test {
companion object {
internal const val prop: Int = 0;
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
interface Test {
companion object {
private val prop = 0;
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
interface Test {
companion object {
private var prop = 0;
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
interface Test {
companion object {
public const val prop: Int = 0;