JVM_IR: do not erase constant non-static field initializers...
...unless in 1.4 mode.
This commit is contained in:
+9
-2
@@ -51,14 +51,21 @@ abstract class InitializersLoweringBase(open val context: CommonBackendContext)
|
|||||||
irClass.declarations.removeAll { it is IrAnonymousInitializer && filter(it) }
|
irClass.declarations.removeAll { it is IrAnonymousInitializer && filter(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun shouldEraseFieldInitializer(irField: IrField): Boolean = true
|
||||||
|
|
||||||
private fun handleField(irClass: IrClass, declaration: IrField): IrStatement? =
|
private fun handleField(irClass: IrClass, declaration: IrField): IrStatement? =
|
||||||
declaration.initializer?.run {
|
declaration.initializer?.run {
|
||||||
val receiver = if (!declaration.isStatic) // TODO isStaticField
|
val receiver = if (!declaration.isStatic) // TODO isStaticField
|
||||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol)
|
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol)
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
declaration.initializer = null
|
val value = if (shouldEraseFieldInitializer(declaration)) {
|
||||||
IrSetFieldImpl(startOffset, endOffset, declaration.symbol, receiver, expression, context.irBuiltIns.unitType)
|
declaration.initializer = null
|
||||||
|
expression
|
||||||
|
} else {
|
||||||
|
expression.deepCopyWithSymbols()
|
||||||
|
}
|
||||||
|
IrSetFieldImpl(startOffset, endOffset, declaration.symbol, receiver, value, context.irBuiltIns.unitType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement =
|
private fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement =
|
||||||
|
|||||||
@@ -173,8 +173,13 @@ private val staticInitializersPhase = makeIrFilePhase(
|
|||||||
description = "Move code from object init blocks and static field initializers to a new <clinit> function"
|
description = "Move code from object init blocks and static field initializers to a new <clinit> function"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val initializersPhase = makeIrFilePhase(
|
private val initializersPhase = makeIrFilePhase<JvmBackendContext>(
|
||||||
::InitializersLowering,
|
{ context ->
|
||||||
|
object : InitializersLowering(context) {
|
||||||
|
override fun shouldEraseFieldInitializer(irField: IrField): Boolean =
|
||||||
|
irField.constantValue(context) == null
|
||||||
|
}
|
||||||
|
},
|
||||||
name = "Initializers",
|
name = "Initializers",
|
||||||
description = "Merge init blocks and field initializers into constructors",
|
description = "Merge init blocks and field initializers into constructors",
|
||||||
stickyPostconditions = setOf(fun(irFile: IrFile) {
|
stickyPostconditions = setOf(fun(irFile: IrFile) {
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ fun IrField.constantValue(context: JvmBackendContext? = null): IrConst<*>? {
|
|||||||
// JVM has a ConstantValue attribute which does two things:
|
// JVM has a ConstantValue attribute which does two things:
|
||||||
// 1. allows the field to be inlined into other modules;
|
// 1. allows the field to be inlined into other modules;
|
||||||
// 2. implicitly generates an initialization of that field in <clinit>
|
// 2. implicitly generates an initialization of that field in <clinit>
|
||||||
// It is only allowed on static final fields of primitive/string types. Java and Kotlin < 1.4
|
// It is only allowed on final fields of primitive/string types. Java and Kotlin < 1.4
|
||||||
// apply it whenever possible; Kotlin >= 1.4 only applies it to `const val`s to avoid making
|
// apply it whenever possible; Kotlin >= 1.4 only applies it to `const val`s to avoid making
|
||||||
// values part of the library's ABI unless explicitly requested by the author.
|
// values part of the library's ABI unless explicitly requested by the author.
|
||||||
val allowImplicitConst =
|
val allowImplicitConst =
|
||||||
context != null && !context.state.languageVersionSettings.supportsFeature(LanguageFeature.NoConstantValueAttributeForNonConstVals)
|
context != null && !context.state.languageVersionSettings.supportsFeature(LanguageFeature.NoConstantValueAttributeForNonConstVals)
|
||||||
val implicitConst = isStatic && isFinal && (origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB ||
|
val implicitConst = isFinal && ((isStatic && origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) ||
|
||||||
(allowImplicitConst && (type.isPrimitiveType() || type.isStringClassType())))
|
(allowImplicitConst && (type.isPrimitiveType() || type.isStringClassType())))
|
||||||
return if (implicitConst || correspondingPropertySymbol?.owner?.isConst == true) value else null
|
return if (implicitConst || correspondingPropertySymbol?.owner?.isConst == true) value else null
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-1
@@ -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
@@ -1,5 +1,4 @@
|
|||||||
// !LANGUAGE: -NoConstantValueAttributeForNonConstVals
|
// !LANGUAGE: -NoConstantValueAttributeForNonConstVals
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
//ALLOW_AST_ACCESS
|
//ALLOW_AST_ACCESS
|
||||||
|
|
||||||
package test
|
package test
|
||||||
|
|||||||
Reference in New Issue
Block a user