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 { val companion = irClass.declarations.find {
it is IrClass && it.isCompanion it is IrClass && it.isCompanion
} as IrClass? ?: return } 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) { when (it) {
is IrProperty -> { is IrProperty ->
val newField = movePropertyFieldToStaticParent(it, companion, irClass, fieldReplacementMap) movePropertyFieldToStaticParent(it, companion, newParent, fieldReplacementMap)
if (newField != null) irClass.declarations.add(newField) is IrAnonymousInitializer ->
} moveAnonymousInitializerToStaticParent(it, companion, newParent)
is IrAnonymousInitializer -> { else ->
val newInitializer = moveAnonymousInitializerToStaticParent(it, companion, irClass) null
irClass.declarations.add(newInitializer)
}
else -> Unit
} }
} }
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) { 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 = "" var result = ""
interface A { interface A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// Checks that accessor are not used because property can be accessed directly. // Checks that accessor are not used because property can be accessed directly.
interface I { interface I {
@@ -1,5 +1,4 @@
// !LANGUAGE: +NoConstantValueAttributeForNonConstVals +JvmFieldInInterface // !LANGUAGE: +NoConstantValueAttributeForNonConstVals +JvmFieldInInterface
// IGNORE_BACKEND: JVM_IR
class C { class C {
val testClassVal = 100 val testClassVal = 100
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
class TestDelegate() { class TestDelegate() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
class TestDelegate() { class TestDelegate() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
interface Test { interface Test {
companion object { companion object {
internal const val prop: Int = 0; internal const val prop: Int = 0;
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
interface Test { interface Test {
companion object { companion object {
private val prop = 0; private val prop = 0;
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
interface Test { interface Test {
companion object { companion object {
private var prop = 0; private var prop = 0;
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
interface Test { interface Test {
companion object { companion object {
public const val prop: Int = 0; public const val prop: Int = 0;