diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt index 3cedacd04f5..80cdcffa06f 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt @@ -61,7 +61,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : return interpreter.withNewCallStack(irCall) { this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall)) valueArguments.forEach { this@withNewCallStack.environment.callStack.addVariable(it) } - }.wrap(this@DefaultCallInterceptor, remainArraysAsIs = true, extendFrom = expectedResultClass) + }.wrap(this@DefaultCallInterceptor, remainArraysAsIs = false, extendFrom = expectedResultClass) } override fun interceptCall(call: IrCall, irFunction: IrFunction, args: List, defaultAction: () -> Unit) { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/ExceptionUtils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/ExceptionUtils.kt index 74f199e8c41..ea6653220a3 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/ExceptionUtils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/ExceptionUtils.kt @@ -8,6 +8,10 @@ package org.jetbrains.kotlin.ir.interpreter.exceptions import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment import org.jetbrains.kotlin.ir.interpreter.state.ExceptionState +internal fun stop(lazyMessage: () -> Any): Nothing { + throw InterpreterAssertionError(lazyMessage().toString()) +} + internal fun verify(value: Boolean) { verify(value) { "Assertion failed" } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt index 22a5efdc086..5925be61d22 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt @@ -24,6 +24,7 @@ internal object IntrinsicEvaluator { ArrayConstructor.canHandleFunctionWithName(fqName, irFunction.origin) -> ArrayConstructor.unwind(irFunction, environment) SourceLocation.canHandleFunctionWithName(fqName, irFunction.origin) -> SourceLocation.unwind(irFunction, environment) AssertIntrinsic.canHandleFunctionWithName(fqName, irFunction.origin) -> AssertIntrinsic.unwind(irFunction, environment) + DataClassArrayToString.canHandleFunctionWithName(fqName, irFunction.origin) -> DataClassArrayToString.unwind(irFunction, environment) else -> null } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt index bec0d775528..8e5b83179ae 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.interpreter.* import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException +import org.jetbrains.kotlin.ir.interpreter.exceptions.stop import org.jetbrains.kotlin.ir.interpreter.state.* import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState @@ -21,6 +22,7 @@ import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.resolveFakeOverride import org.jetbrains.kotlin.types.Variance +import java.util.* internal sealed class IntrinsicBase { abstract fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean @@ -304,4 +306,31 @@ internal object AssertIntrinsic : IntrinsicBase() { 2 -> AssertionError(environment.callStack.popState().asString()).handleUserException(environment) } } +} + +internal object DataClassArrayToString : IntrinsicBase() { + override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { + return fqName == "kotlin.internal.ir.dataClassArrayMemberToString" + } + + private fun arrayToString(array: Any?): String { + return when (array) { + null -> "null" + is Array<*> -> Arrays.toString(array) + is ByteArray -> Arrays.toString(array) + is ShortArray -> Arrays.toString(array) + is IntArray -> Arrays.toString(array) + is LongArray -> Arrays.toString(array) + is CharArray -> Arrays.toString(array) + is BooleanArray -> Arrays.toString(array) + is FloatArray -> Arrays.toString(array) + is DoubleArray -> Arrays.toString(array) + else -> stop { "Only arrays are supported in `dataClassArrayMemberToString` call" } + } + } + + override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { + val array = environment.callStack.getState(irFunction.valueParameters.single().symbol) as Primitive<*> + environment.callStack.pushState(arrayToString(array.value).toState(irFunction.returnType)) + } } \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/dataClass.kt b/compiler/testData/ir/interpreter/dataClass.kt index 14f4a87a9cd..7ab13ee43e8 100644 --- a/compiler/testData/ir/interpreter/dataClass.kt +++ b/compiler/testData/ir/interpreter/dataClass.kt @@ -17,3 +17,11 @@ const val b2 = Person("John", 789).copy("Adam", 123).equals(Person("John", 123456)) const val d = Person("John", 123456).getAsString() + +@CompileTimeCalculation +data class WithArray(val array: Array<*>?, val intArray: IntArray?) + +const val e1 = WithArray(arrayOf(1, 2.0), intArrayOf(1, 2, 3)).toString() +const val e2 = WithArray(null, intArrayOf(1, 2, 3)).toString() +const val e3 = WithArray(arrayOf("1", false), null).toString() +const val e4 = WithArray(null, null).toString()