[IR] Rewrite logic around object interpretation

Basically we want to allow object interpretation only when we try
to access some const val property.

#KT-57810 Fixed
This commit is contained in:
Ivan Kylchik
2023-04-07 23:50:57 +02:00
committed by Space Team
parent 5956e9b500
commit 1ddcdcfc39
4 changed files with 16 additions and 6 deletions
@@ -297,7 +297,8 @@ internal fun IrClass.getSingleAbstractMethod(): IrFunction {
return declarations.filterIsInstance<IrSimpleFunction>().single { it.modality == Modality.ABSTRACT }
}
internal fun IrGetValue.isAccessToNotNullableObject(): Boolean {
internal fun IrExpression?.isAccessToNotNullableObject(): Boolean {
if (this !is IrGetValue) return false
val owner = this.symbol.owner
val expectedClass = this.type.classOrNull?.owner
if (expectedClass == null || !expectedClass.isObject || this.type.isNullable()) return false
@@ -66,6 +66,10 @@ class IrCompileTimeChecker(
return this.asVisited { !mode.mustCheckBodyOf(this) || (this.body?.accept(this@IrCompileTimeChecker, null) ?: true) }
}
private fun IrCall.isGetterToConstVal(): Boolean {
return symbol.owner.correspondingPropertySymbol?.owner?.isConst == true
}
override fun visitCall(expression: IrCall, data: Nothing?): Boolean {
val owner = expression.symbol.owner
if (!mode.canEvaluateFunction(owner, expression)) return false
@@ -78,6 +82,10 @@ class IrCompileTimeChecker(
}
return expression.saveContext {
if (expression.dispatchReceiver.isAccessToNotNullableObject()) {
return@saveContext expression.isGetterToConstVal()
}
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true
val extensionReceiverComputable = expression.extensionReceiver?.accept(this, null) ?: true
if (!visitValueArguments(expression, null)) return@saveContext false
@@ -177,7 +185,7 @@ class IrCompileTimeChecker(
}
override fun visitGetValue(expression: IrGetValue, data: Nothing?): Boolean {
return visitedStack.contains(expression.symbol.owner.parent) || expression.isAccessToNotNullableObject()
return visitedStack.contains(expression.symbol.owner.parent)
}
override fun visitSetValue(expression: IrSetValue, data: Nothing?): Boolean {
@@ -199,7 +207,8 @@ class IrCompileTimeChecker(
isJavaStaticWithPrimitiveOrString() -> owner.initializer?.accept(this, data) == true
expression.receiver == null -> property?.isConst == true && owner.initializer?.accept(this, null) == true
owner.origin == IrDeclarationOrigin.PROPERTY_BACKING_FIELD && property?.isConst == true -> {
val receiverComputable = expression.receiver?.accept(this, null) ?: true
val receiverComputable = (expression.receiver?.accept(this, null) ?: true)
|| expression.isAccessToNotNullableObject()
val initializerComputable = owner.initializer?.accept(this, null) ?: false
receiverComputable && initializerComputable
}
@@ -7,8 +7,8 @@ fun ObjectWithExtension?.nullableExtensionFun(): String =
"Not null"
fun ObjectWithExtension.extensionFun(): String =
if(<!EVALUATED("false")!>this == null<!>)
"Null" // unreachable branch, will be optimized by interpreter
if(this == null)
"Null"
else
"Not null"
@@ -6,7 +6,7 @@
object Test {
fun foo(): String = "foo " + this
fun bar(): String = "bar $this"
fun bar(): String = "<!EVALUATED("bar ")!>bar <!>$this"
fun baz(): String = "baz " + this.toString()
}