From 574c607f1c42f057ac171bd3a6fbc974a83b44ed Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Fri, 4 Jun 2021 13:31:45 +0300 Subject: [PATCH] Support proper subtype check in interpreter for KFunction --- .../kotlin/ir/interpreter/state/State.kt | 15 ++++++++++++++- compiler/testData/ir/interpreter/instanceOf.kt | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt index 361e140d441..c5c4cf5cd37 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt @@ -7,15 +7,20 @@ package org.jetbrains.kotlin.ir.interpreter.state import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException +import org.jetbrains.kotlin.ir.interpreter.isFunction +import org.jetbrains.kotlin.ir.interpreter.isKFunction import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState import org.jetbrains.kotlin.ir.interpreter.state.reflection.ReflectionState import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.isSubclassOf +import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.util.OperatorNameConventions internal interface State { @@ -62,7 +67,15 @@ internal fun State.isSubtypeOf(other: IrType): Boolean { return this.type.arraySubtypeCheck(other) } - return this.irClass.defaultType.isSubtypeOfClass(other.classOrNull!!) + val thisType = this.irClass.defaultType + if (other.isFunction() && thisType.isKFunction()/* TODO || (other.isSuspendFunction && thisType.isKSuspendFunction())*/) { + // KFunction{n} has no super type of Function{n}, + // but the single overridden function of KFunction{n}.invoke is Function{n}.invoke. + val invokeFun = this.irClass.declarations.filterIsInstance().single { it.name == OperatorNameConventions.INVOKE } + return invokeFun.overriddenSymbols.single().owner.parentAsClass.isSubclassOf(other.classOrNull!!.owner) + } + + return thisType.isSubtypeOfClass(other.classOrNull!!) } /** diff --git a/compiler/testData/ir/interpreter/instanceOf.kt b/compiler/testData/ir/interpreter/instanceOf.kt index bf99a885992..6d685d50a43 100644 --- a/compiler/testData/ir/interpreter/instanceOf.kt +++ b/compiler/testData/ir/interpreter/instanceOf.kt @@ -6,8 +6,8 @@ open class A : Base @CompileTimeCalculation class B : A() -const val a1 = 1 is Int -const val a2 = 2 !is Int +const val a1 = { 1 is Int }() // avoid evaluation by native interpreter +const val a2 = { 2 !is Int }() const val b1 = A() is Base const val b2 = A() !is Base @@ -20,3 +20,15 @@ const val c3 = B() is A const val c4 = B() !is A const val c5 = B() is B const val c6 = B() !is B + +@CompileTimeCalculation +fun foo(): Unit {} +@CompileTimeCalculation +fun bar(p1: Int): Unit {} + +const val d1 =::foo is kotlin.reflect.KFunction<*> +const val d2 =::foo is Function0<*> +const val d3 =::foo is Function1<*, *> +const val d4 =::bar is kotlin.reflect.KFunction<*> +const val d5 =::bar is Function0<*> +const val d6 =::bar is Function1<*, *>