From b10fdb919faf90c0d542f34fa55b1ce43e504ff6 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Thu, 10 Jun 2021 18:20:35 +0300 Subject: [PATCH] Support cast to array with reified argument in interpreter --- .../kotlin/ir/interpreter/IrInterpreter.kt | 24 +++++++++++++++---- .../testData/ir/interpreter/safeClassCast.kt | 6 +++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index 525abf77ff5..1e28f9d2974 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -20,12 +20,11 @@ import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy import org.jetbrains.kotlin.ir.interpreter.stack.CallStack import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.* -import org.jetbrains.kotlin.ir.interpreter.state.reflection.KClassState -import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState -import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState -import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState +import org.jetbrains.kotlin.ir.interpreter.state.reflection.* +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.buildSimpleType import org.jetbrains.kotlin.ir.util.* internal interface Instruction { @@ -438,10 +437,25 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal } private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall) { + fun IrClassifierSymbol.getTypeFromStack(): IrType { + return (callStack.getState(this) as KTypeState).irType + } + + fun IrType.replaceArgumentIfReified(): IrType { + if (this !is IrSimpleType) return this + val argument = this.arguments.singleOrNull()?.typeOrNull?.classifierOrNull + return when { + argument is IrTypeParameterSymbol && argument.owner.isReified -> { + this.buildSimpleType { arguments = listOf(argument.getTypeFromStack() as IrTypeArgument) } + } + else -> this + } + } + val typeClassifier = expression.typeOperand.classifierOrFail val isReified = (typeClassifier.owner as? IrTypeParameter)?.isReified == true val isErased = typeClassifier.owner is IrTypeParameter && !isReified - val typeOperand = if (isReified) (callStack.getState(typeClassifier) as KTypeState).irType else expression.typeOperand + val typeOperand = (if (isReified) typeClassifier.getTypeFromStack() else expression.typeOperand).replaceArgumentIfReified() val state = callStack.popState() when (expression.operator) { diff --git a/compiler/testData/ir/interpreter/safeClassCast.kt b/compiler/testData/ir/interpreter/safeClassCast.kt index 3fd046c0272..f4481db99d9 100644 --- a/compiler/testData/ir/interpreter/safeClassCast.kt +++ b/compiler/testData/ir/interpreter/safeClassCast.kt @@ -10,6 +10,8 @@ inline fun bar(): String { return if (listOf() as? T == null) "Can't cast" else "Safe cast" } +inline fun arrayCast(vararg t: T): Array = t as Array + const val a1 = foo() const val a2 = foo() const val a3 = foo() @@ -31,3 +33,7 @@ const val c5 = arrayOf>(listOf(1, 2), listOf(2, 3 const val c6 = arrayOf>(listOf(1, 2), listOf(2, 3)) as? Array> == null const val c7 = Array>(3) { listOf(it, it + 1) } as? Array?> == null const val c8 = Array>(3) { listOf(it, it + 1) } as? Array> == null + +const val d1 = arrayCast(arrayOf(1, 2, 3)).size +const val d2 = arrayCast(*arrayOf(1, 2, 3)).size +const val d3 = arrayCast(1, 2, 3).size