diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt index d05d50fb482..c3dd02ac969 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.lang.invoke.MethodType +import kotlin.math.min internal fun IrFunction.getDispatchReceiver(): IrValueParameterSymbol? = this.dispatchReceiverParameter?.symbol @@ -225,6 +226,24 @@ internal fun IrType.isInterface() = classOrNull?.owner?.kind == ClassKind.INTERF internal fun IrType.isThrowable() = this.getClass()?.fqNameWhenAvailable?.asString() == "kotlin.Throwable" +internal fun IrType.renderType(): String { + var renderedType = this.render() + do { + val index = renderedType.indexOf(" of ") + if (index == -1) break + val replaceUntilComma = renderedType.indexOf(',', index) + val replaceUntilTriangle = renderedType.indexOf('>', index) + val replaceUntil = when { + replaceUntilComma == -1 && replaceUntilTriangle == -1 -> renderedType.length + replaceUntilComma == -1 -> replaceUntilTriangle + replaceUntilTriangle == -1 -> replaceUntilComma + else -> min(replaceUntilComma, replaceUntilTriangle) + } + renderedType = renderedType.replaceRange(index, replaceUntil, "") + } while (true) + return renderedType +} + fun IrClass.internalName(): String { val internalName = StringBuilder(this.name.asString()) generateSequence(this as? IrDeclarationParent) { (it as? IrDeclaration)?.parent } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrCompileTimeChecker.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrCompileTimeChecker.kt index 1b8e9005089..89a669bdb39 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrCompileTimeChecker.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrCompileTimeChecker.kt @@ -188,9 +188,14 @@ class IrCompileTimeChecker( } override fun visitFunctionReference(expression: IrFunctionReference, data: Nothing?): Boolean { - return expression.asVisited { - mode.canEvaluateFunction(expression.symbol.owner) && expression.symbol.owner.body?.accept(this, data) == true - } + val owner = expression.symbol.owner + if (!mode.canEvaluateFunction(owner)) return false + + val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true + val extensionReceiverComputable = expression.extensionReceiver?.accept(this, null) ?: true + val bodyComputable = owner.asVisited { if (mode.canEvaluateBody(owner)) owner.body?.accept(this, null) ?: true else true } + + return dispatchReceiverComputable && extensionReceiverComputable && bodyComputable } override fun visitFunctionExpression(expression: IrFunctionExpression, data: Nothing?): Boolean { @@ -261,6 +266,12 @@ class IrCompileTimeChecker( } override fun visitClassReference(expression: IrClassReference, data: Nothing?): Boolean { - return with(mode) { (expression.symbol.owner as IrClass).isMarkedAsCompileTime() } + return with(mode) { + when (this) { + EvaluationMode.FULL -> true + EvaluationMode.WITH_ANNOTATIONS -> (expression.symbol.owner as IrClass).isMarkedAsCompileTime() + EvaluationMode.ONLY_BUILTINS -> false + } + } } } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/AbstractKPropertyProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/AbstractKPropertyProxy.kt index cb045cc4d1e..d79c103a4c2 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/AbstractKPropertyProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/AbstractKPropertyProxy.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState +import org.jetbrains.kotlin.ir.interpreter.state.KTypeState import org.jetbrains.kotlin.ir.types.IrType import kotlin.reflect.KProperty import kotlin.reflect.KType @@ -38,7 +39,7 @@ internal abstract class AbstractKPropertyProxy( override val annotations: List get() = TODO("Not yet implemented") override val returnType: KType - get() = TODO("Not yet implemented") + get() = KTypeProxy(KTypeState(propertyType), interpreter) override val visibility: KVisibility? get() = state.irClass.visibility.toKVisibility() diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KClassProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KClassProxy.kt index c97601acc24..dad6468172b 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KClassProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KClassProxy.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.internalName import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy @@ -17,9 +16,9 @@ internal class KClassProxy( override val state: KClassState, override val interpreter: IrInterpreter ) : ReflectionProxy, KClass { override val simpleName: String? - get() = state.irClass.name.asString() // TODO return null if class has no name + get() = state.irClass.name.takeIf { !it.isSpecial }?.asString() override val qualifiedName: String? - get() = state.irClass.internalName() + get() = if (!state.irClass.name.isSpecial) state.irClass.internalName() else null @Suppress("UNCHECKED_CAST") override val constructors: Collection> @@ -31,9 +30,9 @@ internal class KClassProxy( override val objectInstance: Proxy? get() = TODO("Not yet implemented") override val typeParameters: List - get() = TODO("Not yet implemented") + get() = state.getTypeParameters(interpreter) override val supertypes: List - get() = TODO("Not yet implemented") + get() = state.getSupertypes(interpreter) override val sealedSubclasses: List> get() = TODO("Not yet implemented") override val annotations: List @@ -65,14 +64,17 @@ internal class KClassProxy( } override fun equals(other: Any?): Boolean { - TODO("Not yet implemented") + if (this === other) return true + if (other !is KClassProxy) return false + + return state == other.state } override fun hashCode(): Int { - TODO("Not yet implemented") + return state.hashCode() } override fun toString(): String { - TODO("Not yet implemented") + return state.toString() } } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt index b1a058eb6c1..f4788b5f9e4 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.KFunctionState +import org.jetbrains.kotlin.ir.interpreter.state.KTypeState import org.jetbrains.kotlin.ir.interpreter.toState import org.jetbrains.kotlin.ir.util.isSuspend import kotlin.reflect.* @@ -37,9 +38,9 @@ internal class KFunctionProxy( override val parameters: List get() = TODO("Not yet implemented") override val returnType: KType - get() = TODO("Not yet implemented") + get() = KTypeProxy(KTypeState(state.irFunction.returnType), interpreter) override val typeParameters: List - get() = TODO("Not yet implemented") + get() = state.getTypeParameters(interpreter) override fun call(vararg args: Any?): Any? { var index = 0 diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KTypeParameterProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KTypeParameterProxy.kt new file mode 100644 index 00000000000..126ad3af11a --- /dev/null +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KTypeParameterProxy.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.interpreter.proxy.reflection + +import org.jetbrains.kotlin.ir.interpreter.IrInterpreter +import org.jetbrains.kotlin.ir.interpreter.state.KTypeParameterState +import org.jetbrains.kotlin.types.Variance +import kotlin.reflect.* + +internal class KTypeParameterProxy( + override val state: KTypeParameterState, override val interpreter: IrInterpreter +) : ReflectionProxy, KTypeParameter { + override val name: String + get() = state.irTypeParameter.name.asString() + override val upperBounds: List + get() = state.getUpperBounds(interpreter) + override val variance: KVariance + get() = when (state.irTypeParameter.variance) { + Variance.INVARIANT -> KVariance.INVARIANT + Variance.IN_VARIANCE -> KVariance.IN + Variance.OUT_VARIANCE -> KVariance.OUT + } + override val isReified: Boolean + get() = state.irTypeParameter.isReified + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is KTypeParameterProxy) return false + + return state == other.state + } + + override fun hashCode(): Int = state.hashCode() + + override fun toString(): String = state.toString() +} \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KTypeProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KTypeProxy.kt new file mode 100644 index 00000000000..f06301c2b94 --- /dev/null +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KTypeProxy.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.interpreter.proxy.reflection + +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.interpreter.IrInterpreter +import org.jetbrains.kotlin.ir.interpreter.state.KClassState +import org.jetbrains.kotlin.ir.interpreter.state.KTypeParameterState +import org.jetbrains.kotlin.ir.interpreter.state.KTypeState +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.isMarkedNullable +import kotlin.reflect.KClassifier +import kotlin.reflect.KType +import kotlin.reflect.KTypeProjection + +internal class KTypeProxy(override val state: KTypeState, override val interpreter: IrInterpreter) : ReflectionProxy, KType { + override val classifier: KClassifier? + get() = when (val classifier = state.irType.classifierOrFail.owner) { + is IrClass -> KClassProxy(KClassState(classifier), interpreter) + is IrTypeParameter -> KTypeParameterProxy(KTypeParameterState(classifier), interpreter) + else -> TODO() + } + override val arguments: List + get() = state.getArguments(interpreter) + override val isMarkedNullable: Boolean + get() = state.irType.isMarkedNullable() + override val annotations: List + get() = TODO("Not yet implemented") + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is KTypeProxy) return false + + return state == other.state + } + + override fun hashCode(): Int = state.hashCode() + + override fun toString(): String = state.toString() +} \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/ReflectionProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/ReflectionProxy.kt index f46b46bda2b..562d59d8e9e 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/ReflectionProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/ReflectionProxy.kt @@ -9,9 +9,11 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy +import org.jetbrains.kotlin.ir.interpreter.state.* import org.jetbrains.kotlin.ir.interpreter.state.KClassState import org.jetbrains.kotlin.ir.interpreter.state.KFunctionState import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState +import org.jetbrains.kotlin.ir.interpreter.state.KTypeState import org.jetbrains.kotlin.ir.interpreter.state.ReflectionState import kotlin.reflect.KVisibility @@ -40,6 +42,8 @@ internal interface ReflectionProxy : Proxy { } is KFunctionState -> KFunctionProxy(this, interpreter) is KClassState -> KClassProxy(this, interpreter) + is KTypeState -> KTypeProxy(this, interpreter) + is KTypeParameterState -> KTypeParameterProxy(this, interpreter) else -> TODO("not supported reference state") } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ReflectionState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ReflectionState.kt index 1079c4542a9..5509c38ee76 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ReflectionState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ReflectionState.kt @@ -13,47 +13,67 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrPropertyReference import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.getLastOverridden +import org.jetbrains.kotlin.ir.interpreter.internalName import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KFunctionProxy import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KProperty1Proxy +import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeParameterProxy +import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy +import org.jetbrains.kotlin.ir.interpreter.renderType import org.jetbrains.kotlin.ir.interpreter.stack.Variable -import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.nameForIrSerialization import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.utils.addToStdlib.cast -import kotlin.reflect.KCallable -import kotlin.reflect.KFunction +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult +import kotlin.reflect.* -internal abstract class ReflectionState(override val irClass: IrClass) : State { +internal abstract class ReflectionState(val irClassifierSymbol: IrClassifierSymbol) : State { + override val irClass: IrClass = irClassifierSymbol.extractClass() override val fields: MutableList = mutableListOf() override val typeArguments: MutableList = mutableListOf() + constructor(irTypeParameter: IrTypeParameter) : this(irTypeParameter.superTypes.firstNotNullResult { it.classifierOrNull }!!) + override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null protected fun renderReceivers(dispatchReceiver: IrType?, extensionReceiver: IrType?): String { return buildString { if (dispatchReceiver != null) { - append(dispatchReceiver.render()) + append(dispatchReceiver.renderType()) append(".") } val addParentheses = dispatchReceiver != null && extensionReceiver != null if (addParentheses) append("(") if (extensionReceiver != null) { - append(extensionReceiver.render()) + append(extensionReceiver.renderType()) append(".") } if (addParentheses) append(")") } } + + companion object { + private fun IrClassifierSymbol.extractClass(): IrClass { + return (owner as? IrClass) ?: (owner as IrTypeParameter).extractAnyClass() + } + + private fun IrTypeParameter.extractAnyClass(): IrClass { + return this.superTypes + .firstNotNullResult { it.classOrNull?.owner ?: (it.classifierOrNull?.owner as? IrTypeParameter)?.extractAnyClass() }!! + } + } } -internal class KClassState(override val irClass: IrClass) : ReflectionState(irClass) { +internal class KClassState(override val irClass: IrClass) : ReflectionState(irClass.symbol) { private var _members: Collection>? = null private var _constructors: Collection>? = null + private var _typeParameters: List? = null + private var _supertypes: List? = null constructor(classReference: IrClassReference) : this(classReference.symbol.owner as IrClass) @@ -78,11 +98,43 @@ internal class KClassState(override val irClass: IrClass) : ReflectionState(irCl .map { KFunctionProxy(KFunctionState(it, interpreter.irBuiltIns.functionFactory), interpreter) as KFunction } return _constructors!! } + + fun getTypeParameters(interpreter: IrInterpreter): List { + if (_typeParameters != null) return _typeParameters!! + _typeParameters = irClass.typeParameters.map { KTypeParameterProxy(KTypeParameterState(it), interpreter) } + return _typeParameters!! + } + + fun getSupertypes(interpreter: IrInterpreter): List { + if (_supertypes != null) return _supertypes!! + _supertypes = (irClass.superTypes.map { it } + interpreter.irBuiltIns.anyType).toSet() + .map { KTypeProxy(KTypeState(it), interpreter) } + return _supertypes!! + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as KClassState + + if (irClass != other.irClass) return false + + return true + } + + override fun hashCode(): Int { + return irClass.hashCode() + } + + override fun toString(): String { + return "class ${irClass.internalName()}" + } } internal class KPropertyState( val property: IrProperty, val dispatchReceiver: State?, val extensionReceiver: State? -) : ReflectionState(property.parentAsClass) { +) : ReflectionState(property.parentAsClass.symbol) { constructor(propertyReference: IrPropertyReference, dispatchReceiver: State?, extensionReceiver: State?) : this(propertyReference.symbol.owner, dispatchReceiver, extensionReceiver) @@ -133,18 +185,25 @@ internal class KPropertyState( override fun toString(): String { val prefix = if (property.isVar) "var" else "val" val receivers = renderReceivers(property.getter?.dispatchReceiverParameter?.type, property.getter?.extensionReceiverParameter?.type) - val returnType = property.getter!!.returnType.render() + val returnType = property.getter!!.returnType.renderType() return "$prefix $receivers${property.name}: $returnType" } } -internal class KFunctionState(val irFunction: IrFunction, override val irClass: IrClass) : ReflectionState(irClass) { +internal class KFunctionState(val irFunction: IrFunction, override val irClass: IrClass) : ReflectionState(irClass.symbol) { override val fields: MutableList = mutableListOf() override val typeArguments: MutableList = mutableListOf() + private var _typeParameters: List? = null constructor(functionReference: IrFunctionReference) : this(functionReference.symbol.owner, functionReference.type.classOrNull!!.owner) constructor(irFunction: IrFunction, functionFactory: IrAbstractFunctionFactory) : - this(irFunction, functionFactory.functionN(irFunction.valueParameters.size)) + this(irFunction, functionFactory.kFunctionN(irFunction.valueParameters.size)) + + fun getTypeParameters(interpreter: IrInterpreter): List { + if (_typeParameters != null) return _typeParameters!! + _typeParameters = irClass.typeParameters.map { KTypeParameterProxy(KTypeParameterState(it), interpreter) } + return _typeParameters!! + } private val invokeSymbol = irClass.declarations .single { it.nameForIrSerialization.asString() == "invoke" } @@ -163,17 +222,96 @@ internal class KFunctionState(val irFunction: IrFunction, override val irClass: override fun toString(): String { return if (isLambda()) { - val receiver = (irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type)?.render() - val arguments = irFunction.valueParameters.joinToString(prefix = "(", postfix = ")") { it.type.render() } - val returnType = irFunction.returnType.render() + val receiver = (irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type)?.renderType() + val arguments = irFunction.valueParameters.joinToString(prefix = "(", postfix = ")") { it.type.renderType() } + val returnType = irFunction.returnType.renderType() ("$arguments -> $returnType").let { if (receiver != null) "$receiver.$it" else it } } else { val dispatchReceiver = irFunction.parentAsClass.defaultType // = instanceReceiverParameter val extensionReceiver = irFunction.extensionReceiverParameter?.type val receivers = if (irFunction is IrConstructor) "" else renderReceivers(dispatchReceiver, extensionReceiver) - val arguments = irFunction.valueParameters.joinToString(prefix = "(", postfix = ")") { it.type.render() } - val returnType = irFunction.returnType.render() + val arguments = irFunction.valueParameters.joinToString(prefix = "(", postfix = ")") { it.type.renderType() } + val returnType = irFunction.returnType.renderType() "fun $receivers${irFunction.name}$arguments: $returnType" } } +} + +internal class KTypeState(val irType: IrType) : ReflectionState(irType.classifierOrFail) { + private var _arguments: List? = null + + fun getArguments(interpreter: IrInterpreter): List { + if (_arguments != null) return _arguments!! + _arguments = (irType as IrSimpleType).arguments + .map { + when (it.getVariance()) { + Variance.INVARIANT -> KTypeProjection.invariant(KTypeProxy(KTypeState(it.typeOrNull!!), interpreter)) + Variance.IN_VARIANCE -> KTypeProjection.contravariant(KTypeProxy(KTypeState(it.typeOrNull!!), interpreter)) + Variance.OUT_VARIANCE -> KTypeProjection.covariant(KTypeProxy(KTypeState(it.typeOrNull!!), interpreter)) + null -> KTypeProjection.STAR + } + } + return _arguments!! + } + + private fun IrTypeArgument.getVariance(): Variance? { + return when (this) { + is IrSimpleType -> Variance.INVARIANT + is IrTypeProjection -> this.variance + is IrStarProjection -> null + else -> TODO() + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as KTypeState + + if (irType != other.irType) return false + + return true + } + + override fun hashCode(): Int { + return irType.hashCode() + } + + override fun toString(): String { + return irType.renderType() + } +} + +internal class KTypeParameterState(val irTypeParameter: IrTypeParameter) : ReflectionState(irTypeParameter) { + private var _upperBounds: List? = null + + fun getUpperBounds(interpreter: IrInterpreter): List { + if (_upperBounds != null) return _upperBounds!! + _upperBounds = irTypeParameter.superTypes.map { KTypeProxy(KTypeState(it), interpreter) } + return _upperBounds!! + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as KTypeParameterState + + if (irTypeParameter != other.irTypeParameter) return false + + return true + } + + override fun hashCode(): Int { + return irTypeParameter.hashCode() + } + + override fun toString(): String { + return irTypeParameter.name.asString() + } +} + +internal class KParameterState(val irType: IrType) : ReflectionState(irType.classifierOrFail) { + } \ No newline at end of file