MoveCompanionObjectFields: copy constants into interfaces
Fields having const attribute in companion objects are observable in Java and should be copied to outer interfaces.
This commit is contained in:
committed by
max-kammerer
parent
6ff776ba65
commit
75646f97a4
@@ -105,7 +105,7 @@ val jvmPhases = namedIrFilePhase<JvmBackendContext>(
|
|||||||
|
|
||||||
lateinitPhase then
|
lateinitPhase then
|
||||||
|
|
||||||
moveCompanionObjectFieldsPhase then
|
moveOrCopyCompanionObjectFieldsPhase then
|
||||||
propertyReferencePhase then
|
propertyReferencePhase then
|
||||||
constPhase then
|
constPhase then
|
||||||
propertiesToFieldsPhase then
|
propertiesToFieldsPhase then
|
||||||
|
|||||||
+38
-11
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedFieldDescriptor
|
|||||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
|
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
|
||||||
import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference
|
import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
@@ -31,19 +32,21 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
||||||
|
|
||||||
internal val moveCompanionObjectFieldsPhase = makeIrFilePhase(
|
internal val moveOrCopyCompanionObjectFieldsPhase = makeIrFilePhase(
|
||||||
::MoveCompanionObjectFieldsLowering,
|
::MoveOrCopyCompanionObjectFieldsLowering,
|
||||||
name = "MoveCompanionObjectFields",
|
name = "MoveOrCopyCompanionObjectFields",
|
||||||
description = "Move companion object fields to static fields of companion's owner"
|
description = "Move and/or copy companion object fields to static fields of companion's owner"
|
||||||
)
|
)
|
||||||
|
|
||||||
private class MoveCompanionObjectFieldsLowering(val context: CommonBackendContext) : ClassLoweringPass {
|
private class MoveOrCopyCompanionObjectFieldsLowering(val context: CommonBackendContext) : ClassLoweringPass {
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
val fieldReplacementMap = mutableMapOf<IrFieldSymbol, IrFieldSymbol>()
|
val fieldReplacementMap = mutableMapOf<IrFieldSymbol, IrFieldSymbol>()
|
||||||
if (irClass.isObject && !irClass.isCompanion && irClass.visibility != Visibilities.LOCAL) {
|
if (irClass.isObject && !irClass.isCompanion && irClass.visibility != Visibilities.LOCAL) {
|
||||||
handleObject(irClass, fieldReplacementMap)
|
handleObject(irClass, fieldReplacementMap)
|
||||||
} else {
|
} else {
|
||||||
handleClass(irClass, fieldReplacementMap)
|
handleClass(irClass, fieldReplacementMap)
|
||||||
|
if (irClass.isJvmInterface)
|
||||||
|
copyConsts(irClass)
|
||||||
}
|
}
|
||||||
irClass.replaceFieldReferences(fieldReplacementMap)
|
irClass.replaceFieldReferences(fieldReplacementMap)
|
||||||
}
|
}
|
||||||
@@ -83,28 +86,52 @@ private class MoveCompanionObjectFieldsLowering(val context: CommonBackendContex
|
|||||||
companion.declarations.removeAll { it is IrAnonymousInitializer }
|
companion.declarations.removeAll { it is IrAnonymousInitializer }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun copyConsts(irClass: IrClass) {
|
||||||
|
val companion = irClass.declarations.find {
|
||||||
|
it is IrClass && it.isCompanion
|
||||||
|
} as IrClass? ?: return
|
||||||
|
companion.declarations.filter { it is IrProperty && it.isConst }.mapNotNullTo(irClass.declarations) {
|
||||||
|
copyPropertyFieldToStaticParent(it as IrProperty, companion, irClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrClass.allFieldsAreJvmField() =
|
private fun IrClass.allFieldsAreJvmField() =
|
||||||
declarations.filterIsInstance<IrProperty>()
|
declarations.filterIsInstance<IrProperty>()
|
||||||
.mapNotNull { it.backingField }.all { it.hasAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME) }
|
.mapNotNull { it.backingField }.all { it.hasAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME) }
|
||||||
|
|
||||||
private fun movePropertyFieldToStaticParent(
|
// If fieldReplacementMap is null / unspecified, keep the old field and don't update the references.
|
||||||
|
private fun moveOrCopyPropertyFieldToStaticParent(
|
||||||
irProperty: IrProperty,
|
irProperty: IrProperty,
|
||||||
propertyParent: IrClass,
|
propertyParent: IrClass,
|
||||||
fieldParent: IrClass,
|
fieldParent: IrClass,
|
||||||
fieldReplacementMap: MutableMap<IrFieldSymbol, IrFieldSymbol>
|
fieldReplacementMap: MutableMap<IrFieldSymbol, IrFieldSymbol>? = null
|
||||||
): IrField? {
|
): IrField? {
|
||||||
if (irProperty.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return null
|
if (irProperty.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return null
|
||||||
val oldField = irProperty.backingField ?: return null
|
val oldField = irProperty.backingField ?: return null
|
||||||
val newField = createStaticBackingField(oldField, propertyParent, fieldParent)
|
val newField = createStaticBackingField(oldField, propertyParent, fieldParent)
|
||||||
|
|
||||||
irProperty.backingField = newField
|
fieldReplacementMap?.run {
|
||||||
newField.correspondingPropertySymbol = irProperty.symbol
|
irProperty.backingField = newField
|
||||||
|
newField.correspondingPropertySymbol = irProperty.symbol
|
||||||
fieldReplacementMap[oldField.symbol] = newField.symbol
|
put(oldField.symbol, newField.symbol)
|
||||||
|
}
|
||||||
|
|
||||||
return newField
|
return newField
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun movePropertyFieldToStaticParent(
|
||||||
|
irProperty: IrProperty,
|
||||||
|
propertyParent: IrClass,
|
||||||
|
fieldParent: IrClass,
|
||||||
|
fieldReplacementMap: MutableMap<IrFieldSymbol, IrFieldSymbol>? = null
|
||||||
|
): IrField? = moveOrCopyPropertyFieldToStaticParent(irProperty, propertyParent, fieldParent, fieldReplacementMap)
|
||||||
|
|
||||||
|
private fun copyPropertyFieldToStaticParent(
|
||||||
|
irProperty: IrProperty,
|
||||||
|
propertyParent: IrClass,
|
||||||
|
fieldParent: IrClass
|
||||||
|
): IrField? = moveOrCopyPropertyFieldToStaticParent(irProperty, propertyParent, fieldParent)
|
||||||
|
|
||||||
private fun moveAnonymousInitializerToStaticParent(
|
private fun moveAnonymousInitializerToStaticParent(
|
||||||
oldInitializer: IrAnonymousInitializer,
|
oldInitializer: IrAnonymousInitializer,
|
||||||
oldParent: IrClass,
|
oldParent: IrClass,
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
// FILE: JavaClass.java
|
// FILE: JavaClass.java
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// !LANGUAGE: +NestedClassesInAnnotations
|
// !LANGUAGE: +NestedClassesInAnnotations
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// FILE: Foo.java
|
// FILE: Foo.java
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// FILE: CompanionInitialization.java
|
// FILE: CompanionInitialization.java
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
annotation class AString(val value: String)
|
annotation class AString(val value: String)
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
interface Test {
|
interface Test {
|
||||||
|
|||||||
Reference in New Issue
Block a user