JVM_IR: support @JvmStatic transformations in LateinitLowering

#KT-46759 Fixed
This commit is contained in:
pyos
2021-05-19 10:16:26 +02:00
committed by TeamCityServer
parent f1f13b6e97
commit b2ef854aa1
3 changed files with 35 additions and 23 deletions
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrSetValueImpl
import org.jetbrains.kotlin.ir.types.isMarkedNullable
import org.jetbrains.kotlin.ir.types.isPrimitiveType
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -180,18 +181,15 @@ class LateinitUsageLowering(val backendContext: CommonBackendContext) : BodyLowe
if (!Symbols.isLateinitIsInitializedPropertyGetter(expression.symbol)) return expression
val receiver = expression.extensionReceiver as IrPropertyReference
val property =
receiver.getter?.owner?.resolveFakeOverride()?.correspondingPropertySymbol!!.owner.also { assert(it.isLateinit) }
val nullableField =
backendContext.buildOrGetNullableField(
property.backingField ?: error("Lateinit property is supposed to have backing field")
)
return expression.run { backendContext.createIrBuilder(symbol, startOffset, endOffset) }.run {
irNotEquals(irGetField(receiver.dispatchReceiver, nullableField), irNull())
return expression.extensionReceiver!!.replaceTailExpression {
require(it is IrPropertyReference) { "isInitialized cannot be invoked on ${it.render()}" }
val property = it.getter?.owner?.resolveFakeOverride()?.correspondingPropertySymbol?.owner
require(property?.isLateinit == true) { "isInitialized invoked on non-lateinit property ${property?.render()}" }
val backingField = property?.backingField ?: error("Lateinit property is supposed to have a backing field")
// This is not the right scope symbol, but we don't use it anyway.
backendContext.createIrBuilder(it.symbol, expression.startOffset, expression.endOffset).run {
irNotEquals(irGetField(it.dispatchReceiver, backendContext.buildOrGetNullableField(backingField)), irNull())
}
}
}
})
@@ -208,9 +206,24 @@ private fun CommonBackendContext.buildOrGetNullableField(originalField: IrField)
}.apply {
parent = originalField.parent
correspondingPropertySymbol = originalField.correspondingPropertySymbol
annotations += originalField.annotations
annotations = originalField.annotations
}
}
}
private val IrProperty.isRealLateinit get() = isLateinit && !isFakeOverride
private inline fun IrExpression.replaceTailExpression(crossinline transform: (IrExpression) -> IrExpression): IrExpression {
var current = this
var block: IrContainerExpression? = null
while (current is IrContainerExpression) {
block = current
current = current.statements.last() as IrExpression
}
current = transform(current)
if (block == null) {
return current
}
block.statements[block.statements.size - 1] = current
return this
}
@@ -2,11 +2,13 @@
// TARGET_BACKEND: JVM
object Test {
@JvmStatic
fun foo(x: String, y: String = "") = x + y
fun foo(x: String, y: String = "") = x + value
var value = ""
}
fun callFoo(f: (String) -> String, value: String) = f(value)
fun test() = Test
fun test() = Test.apply { value = "K" }
fun box() = callFoo(Test::foo, "O") + callFoo(test()::foo, "K")
fun box() = callFoo(Test::foo, "O") + callFoo(test()::foo, "")
@@ -1,10 +1,8 @@
// WITH_RUNTIME
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
object Test {
@JvmStatic
lateinit var value: Any
lateinit var value: String
val isInitialized
get() = Test::value.isInitialized
@@ -12,12 +10,11 @@ object Test {
val isInitializedThroughFn
get() = self()::value.isInitialized
fun self() = Test
fun self() = Test.apply { value = "OK" }
}
fun box(): String {
if (Test.isInitialized) return "fail 1"
Test.value = "OK"
if (!Test.isInitializedThroughFn) return "fail 2"
return Test.value as String
}
return Test.value
}