From ddd03373cc27d8f3b67cd79ca1ae2e17f83e5d74 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Mon, 22 Jun 2020 15:39:16 +0300 Subject: [PATCH] Allow to interpret toString method from Any class for ONLY_BUILTINS mode This change aims to support string concatenation operation with const properties --- .../backend/evaluate/IrConstTransformer.kt | 19 +++++-------------- .../ir/interpreter/IrCompileTimeChecker.kt | 11 +++++++---- .../properties/const/interfaceCompanion.kt | 1 - 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/evaluate/IrConstTransformer.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/evaluate/IrConstTransformer.kt index 64dff20e62e..56854ead107 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/evaluate/IrConstTransformer.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/evaluate/IrConstTransformer.kt @@ -10,17 +10,9 @@ import org.jetbrains.kotlin.ir.interpreter.IrCompileTimeChecker import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.toIrConst import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrField -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -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.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid fun evaluateConstants(irModuleFragment: IrModuleFragment) { @@ -48,11 +40,10 @@ class IrConstTransformer(irModuleFragment: IrModuleFragment) : IrElementTransfor if (expression is IrConst<*>) return declaration val isCompileTimeComputable = expression.accept(IrCompileTimeChecker(declaration, mode = EvaluationMode.ONLY_BUILTINS), null) val isConst = declaration.correspondingPropertySymbol?.owner?.isConst == true - if (isConst && !isCompileTimeComputable) { - //throw AssertionError("Const property is used only with functions annotated as CompileTimeCalculation: " + declaration.dump()) - } else if (isCompileTimeComputable) { + if (isConst && isCompileTimeComputable) { initializer.expression = interpreter.interpret(expression).replaceIfError(expression) } + return declaration } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrCompileTimeChecker.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrCompileTimeChecker.kt index 295660ba5db..2feeda83f93 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrCompileTimeChecker.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrCompileTimeChecker.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* 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.isString import org.jetbrains.kotlin.ir.util.* @@ -34,18 +35,20 @@ class IrCompileTimeChecker( private fun IrDeclaration.isContract() = isMarkedWith(contractsDslAnnotation) private fun IrDeclaration.isMarkedAsEvaluateIntrinsic() = isMarkedWith(evaluateIntrinsicAnnotation) - private fun IrDeclaration.isMarkedAsCompileTime(): Boolean { - if (mode == EvaluationMode.FULL) + private fun IrDeclaration.isMarkedAsCompileTime(expression: IrCall? = null): Boolean { + if (mode == EvaluationMode.FULL) { return isMarkedWith(compileTimeAnnotation) || (this is IrSimpleFunction && this.isFakeOverride && this.overriddenSymbols.any { it.owner.isMarkedAsCompileTime() }) || this.parentClassOrNull?.fqNameWhenAvailable?.asString() in compileTimeTypeAliases + } val parent = this.parentClassOrNull val parentType = parent?.defaultType return when { 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") - 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 } } @@ -92,7 +95,7 @@ class IrCompileTimeChecker( if (expression.symbol.owner.isContract()) return false 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 extensionReceiverComputable = expression.extensionReceiver?.accept(this, null) ?: true if (!visitValueParameters(expression, null)) return false diff --git a/compiler/testData/codegen/box/properties/const/interfaceCompanion.kt b/compiler/testData/codegen/box/properties/const/interfaceCompanion.kt index 918d37bd9ce..f3d3c2b35be 100644 --- a/compiler/testData/codegen/box/properties/const/interfaceCompanion.kt +++ b/compiler/testData/codegen/box/properties/const/interfaceCompanion.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME