Allow to interpret toString method from Any class for ONLY_BUILTINS mode

This change aims to support string concatenation operation with const
properties
This commit is contained in:
Ivan Kylchik
2020-06-22 15:39:16 +03:00
parent 6f4f7dd090
commit ddd03373cc
3 changed files with 12 additions and 19 deletions
@@ -10,17 +10,9 @@ import org.jetbrains.kotlin.ir.interpreter.IrCompileTimeChecker
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.toIrConst import org.jetbrains.kotlin.ir.interpreter.toIrConst
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrErrorExpression
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.types.typeOrNull
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
fun evaluateConstants(irModuleFragment: IrModuleFragment) { fun evaluateConstants(irModuleFragment: IrModuleFragment) {
@@ -48,11 +40,10 @@ class IrConstTransformer(irModuleFragment: IrModuleFragment) : IrElementTransfor
if (expression is IrConst<*>) return declaration if (expression is IrConst<*>) return declaration
val isCompileTimeComputable = expression.accept(IrCompileTimeChecker(declaration, mode = EvaluationMode.ONLY_BUILTINS), null) val isCompileTimeComputable = expression.accept(IrCompileTimeChecker(declaration, mode = EvaluationMode.ONLY_BUILTINS), null)
val isConst = declaration.correspondingPropertySymbol?.owner?.isConst == true val isConst = declaration.correspondingPropertySymbol?.owner?.isConst == true
if (isConst && !isCompileTimeComputable) { if (isConst && isCompileTimeComputable) {
//throw AssertionError("Const property is used only with functions annotated as CompileTimeCalculation: " + declaration.dump())
} else if (isCompileTimeComputable) {
initializer.expression = interpreter.interpret(expression).replaceIfError(expression) initializer.expression = interpreter.interpret(expression).replaceIfError(expression)
} }
return declaration return declaration
} }
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.isPrimitiveType import org.jetbrains.kotlin.ir.types.isPrimitiveType
import org.jetbrains.kotlin.ir.types.isString import org.jetbrains.kotlin.ir.types.isString
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
@@ -34,18 +35,20 @@ class IrCompileTimeChecker(
private fun IrDeclaration.isContract() = isMarkedWith(contractsDslAnnotation) private fun IrDeclaration.isContract() = isMarkedWith(contractsDslAnnotation)
private fun IrDeclaration.isMarkedAsEvaluateIntrinsic() = isMarkedWith(evaluateIntrinsicAnnotation) private fun IrDeclaration.isMarkedAsEvaluateIntrinsic() = isMarkedWith(evaluateIntrinsicAnnotation)
private fun IrDeclaration.isMarkedAsCompileTime(): Boolean { private fun IrDeclaration.isMarkedAsCompileTime(expression: IrCall? = null): Boolean {
if (mode == EvaluationMode.FULL) if (mode == EvaluationMode.FULL) {
return isMarkedWith(compileTimeAnnotation) || return isMarkedWith(compileTimeAnnotation) ||
(this is IrSimpleFunction && this.isFakeOverride && this.overriddenSymbols.any { it.owner.isMarkedAsCompileTime() }) || (this is IrSimpleFunction && this.isFakeOverride && this.overriddenSymbols.any { it.owner.isMarkedAsCompileTime() }) ||
this.parentClassOrNull?.fqNameWhenAvailable?.asString() in compileTimeTypeAliases this.parentClassOrNull?.fqNameWhenAvailable?.asString() in compileTimeTypeAliases
}
val parent = this.parentClassOrNull val parent = this.parentClassOrNull
val parentType = parent?.defaultType val parentType = parent?.defaultType
return when { return when {
parentType?.isPrimitiveType() == true -> (this as IrFunction).name.asString() !in setOf("inc", "dec", "rangeTo", "hashCode") parentType?.isPrimitiveType() == true -> (this as IrFunction).name.asString() !in setOf("inc", "dec", "rangeTo", "hashCode")
parentType?.isString() == true -> (this as IrDeclarationWithName).name.asString() !in setOf("subSequence", "hashCode") parentType?.isString() == true -> (this as IrDeclarationWithName).name.asString() !in setOf("subSequence", "hashCode")
parent?.isCompanion == true -> parent.parentClassOrNull?.defaultType?.let { it.isPrimitiveType() || it.isUnsigned() } == true parentType?.isAny() == true -> (this as IrFunction).name.asString() == "toString" && expression?.dispatchReceiver !is IrGetObjectValue
parent?.isObject == true -> parent.parentClassOrNull?.defaultType?.let { it.isPrimitiveType() || it.isUnsigned() } == true
else -> false else -> false
} }
} }
@@ -92,7 +95,7 @@ class IrCompileTimeChecker(
if (expression.symbol.owner.isContract()) return false if (expression.symbol.owner.isContract()) return false
val property = (expression.symbol.owner as? IrSimpleFunction)?.correspondingPropertySymbol?.owner val property = (expression.symbol.owner as? IrSimpleFunction)?.correspondingPropertySymbol?.owner
if (expression.symbol.owner.isMarkedAsCompileTime() || property.isCompileTime()) { if (expression.symbol.owner.isMarkedAsCompileTime(expression) || property.isCompileTime()) {
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true
val extensionReceiverComputable = expression.extensionReceiver?.accept(this, null) ?: true val extensionReceiverComputable = expression.extensionReceiver?.accept(this, null) ?: true
if (!visitValueParameters(expression, null)) return false if (!visitValueParameters(expression, null)) return false
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_RUNTIME // WITH_RUNTIME