From f34a08cbbf41f7e3bb2db4f3fa7972085081d4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Wed, 7 Aug 2019 14:19:17 +0200 Subject: [PATCH] JVM IR: Convert interface companion fields to static fields. --- .../MoveCompanionObjectFieldsLowering.kt | 30 +++++++++++-------- .../codegen/box/objects/interfaceCompanion.kt | 4 +++ .../bytecodeText/companion/kt14258_5.kt | 1 - .../nonConstValHasNoDefaultValue_after.kt | 1 - .../trait/delegatedProtectedVar.kt | 1 - .../classObject/trait/delegatedPublicVal.kt | 1 - .../classObject/trait/internalConstVal.kt | 1 - .../property/classObject/trait/privateVal.kt | 1 - .../property/classObject/trait/privateVar.kt | 1 - .../classObject/trait/publicConstVal.kt | 1 - 10 files changed, 22 insertions(+), 20 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt index 61bddb13f55..58fac5437b6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt @@ -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) { diff --git a/compiler/testData/codegen/box/objects/interfaceCompanion.kt b/compiler/testData/codegen/box/objects/interfaceCompanion.kt index 924329d3b37..ceda1fb8c31 100644 --- a/compiler/testData/codegen/box/objects/interfaceCompanion.kt +++ b/compiler/testData/codegen/box/objects/interfaceCompanion.kt @@ -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 { diff --git a/compiler/testData/codegen/bytecodeText/companion/kt14258_5.kt b/compiler/testData/codegen/bytecodeText/companion/kt14258_5.kt index 78817b4d5f5..e88abc9c939 100644 --- a/compiler/testData/codegen/bytecodeText/companion/kt14258_5.kt +++ b/compiler/testData/codegen/bytecodeText/companion/kt14258_5.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // Checks that accessor are not used because property can be accessed directly. interface I { diff --git a/compiler/testData/codegen/bytecodeText/constProperty/nonConstValHasNoDefaultValue_after.kt b/compiler/testData/codegen/bytecodeText/constProperty/nonConstValHasNoDefaultValue_after.kt index 42c32aa398f..0a623ebad81 100644 --- a/compiler/testData/codegen/bytecodeText/constProperty/nonConstValHasNoDefaultValue_after.kt +++ b/compiler/testData/codegen/bytecodeText/constProperty/nonConstValHasNoDefaultValue_after.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +NoConstantValueAttributeForNonConstVals +JvmFieldInInterface -// IGNORE_BACKEND: JVM_IR class C { val testClassVal = 100 diff --git a/compiler/testData/writeFlags/property/classObject/trait/delegatedProtectedVar.kt b/compiler/testData/writeFlags/property/classObject/trait/delegatedProtectedVar.kt index 239c013d0e3..3cbf9bf1bc4 100644 --- a/compiler/testData/writeFlags/property/classObject/trait/delegatedProtectedVar.kt +++ b/compiler/testData/writeFlags/property/classObject/trait/delegatedProtectedVar.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR import kotlin.reflect.KProperty class TestDelegate() { diff --git a/compiler/testData/writeFlags/property/classObject/trait/delegatedPublicVal.kt b/compiler/testData/writeFlags/property/classObject/trait/delegatedPublicVal.kt index cac17d939f4..667b1f67ed5 100644 --- a/compiler/testData/writeFlags/property/classObject/trait/delegatedPublicVal.kt +++ b/compiler/testData/writeFlags/property/classObject/trait/delegatedPublicVal.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR import kotlin.reflect.KProperty class TestDelegate() { diff --git a/compiler/testData/writeFlags/property/classObject/trait/internalConstVal.kt b/compiler/testData/writeFlags/property/classObject/trait/internalConstVal.kt index e21bc2b4640..147ae2ce4f9 100644 --- a/compiler/testData/writeFlags/property/classObject/trait/internalConstVal.kt +++ b/compiler/testData/writeFlags/property/classObject/trait/internalConstVal.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR interface Test { companion object { internal const val prop: Int = 0; diff --git a/compiler/testData/writeFlags/property/classObject/trait/privateVal.kt b/compiler/testData/writeFlags/property/classObject/trait/privateVal.kt index a59bdece66c..99c63881837 100644 --- a/compiler/testData/writeFlags/property/classObject/trait/privateVal.kt +++ b/compiler/testData/writeFlags/property/classObject/trait/privateVal.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR interface Test { companion object { private val prop = 0; diff --git a/compiler/testData/writeFlags/property/classObject/trait/privateVar.kt b/compiler/testData/writeFlags/property/classObject/trait/privateVar.kt index 4a6b1744b91..6939583cad7 100644 --- a/compiler/testData/writeFlags/property/classObject/trait/privateVar.kt +++ b/compiler/testData/writeFlags/property/classObject/trait/privateVar.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR interface Test { companion object { private var prop = 0; diff --git a/compiler/testData/writeFlags/property/classObject/trait/publicConstVal.kt b/compiler/testData/writeFlags/property/classObject/trait/publicConstVal.kt index 4a39e67a65d..8ec4a97d406 100644 --- a/compiler/testData/writeFlags/property/classObject/trait/publicConstVal.kt +++ b/compiler/testData/writeFlags/property/classObject/trait/publicConstVal.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR interface Test { companion object { public const val prop: Int = 0;