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 b5e82c2decf..6fd91d59243 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 @@ -94,9 +94,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : val function = when (val symbol = invokedFunction.symbol) { is IrSimpleFunctionSymbol -> { - val irCall = IrCallImpl.fromSymbolOwner( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, invokedFunction.returnType, invokedFunction.symbol as IrSimpleFunctionSymbol - ) + val irCall = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, invokedFunction.returnType, symbol) val actualFunction = dispatchReceiver?.getIrFunctionByIrCall(irCall) ?: invokedFunction callStack.newFrame(actualFunction) callStack.addInstruction(SimpleInstruction(actualFunction)) @@ -118,6 +116,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : function.dispatchReceiverParameter?.let { callStack.addVariable(Variable(it.symbol, dispatchReceiver!!)) } function.extensionReceiverParameter?.let { callStack.addVariable(Variable(it.symbol, extensionReceiver!!)) } function.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) } + if (invokedFunction.symbol is IrConstructorSymbol) return callStack.loadUpValues(functionState) if (extensionReceiver is StateWithClosure) callStack.loadUpValues(extensionReceiver) @@ -125,7 +124,6 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : generateSequence(dispatchReceiver.outerClass) { (it.state as? Complex)?.outerClass }.forEach { callStack.addVariable(it) } } - if (invokedFunction.symbol is IrConstructorSymbol) return this.interceptCall(call, function, listOfNotNull(dispatchReceiver, extensionReceiver) + valueArguments) { callStack.addInstruction(CompoundInstruction(function)) } 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 3a7a5d302b7..6d409bbc636 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 @@ -426,6 +426,7 @@ class IrInterpreter private constructor( val cleanEnumSuperCall = fun() { enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null + callStack.popState() // result of constructor must be dropped, because next instruction will be `IrGetEnumValue` callStack.dropSubFrame() } @@ -606,6 +607,16 @@ class IrInterpreter private constructor( callStack.dropSubFrame() val propertyState = KPropertyState(propertyReference, receiver) + + fun List.addToFields() { + (0 until propertyReference.typeArgumentsCount).forEach { index -> + val kTypeState = KTypeState(propertyReference.getTypeArgument(index)!!, irBuiltIns.anyClass.owner) + propertyState.fields += Variable(this[index].symbol, kTypeState) + } + } + propertyReference.getter?.owner?.typeParameters?.addToFields() + propertyReference.setter?.owner?.typeParameters?.addToFields() + callStack.pushState(propertyState) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt index 97354e4cb50..677682e4458 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.isNull import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState import org.jetbrains.kotlin.ir.interpreter.toState +import org.jetbrains.kotlin.ir.util.isObject import org.jetbrains.kotlin.ir.util.resolveFakeOverride import kotlin.reflect.* @@ -66,6 +67,7 @@ internal class KMutableProperty0Proxy( checkArguments(1, args.size) // null receiver <=> property is on top level verify(state.receiver != null) { "Cannot interpret set method on top level properties" } + verify(state.receiver?.irClass?.isObject != true) { "Cannot interpret set method on property of object" } val receiver = state.receiver!! val newValue = args.single().toState(propertyType) setter.getExtensionReceiver() diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt index ac7f6324e52..5ff8d376529 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt @@ -5,23 +5,35 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState +import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState import org.jetbrains.kotlin.ir.interpreter.toState +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.classifierOrFail import kotlin.reflect.* internal open class KProperty1Proxy( override val state: KPropertyState, override val callInterceptor: CallInterceptor ) : AbstractKPropertyProxy(state, callInterceptor), KProperty1 { + protected fun IrValueParameter.getActualType(): IrType { + return when (this.type.classOrNull) { + null -> (state.getField(this.type.classifierOrFail) as KTypeState).irType + else -> this.type + } + } + override val getter: KProperty1.Getter get() = object : Getter(state.property.getter!!), KProperty1.Getter { override fun invoke(p1: Any?): Any? = call(p1) override fun call(vararg args: Any?): Any? { checkArguments(1, args.size) - val receiverParameter = getter.dispatchReceiverParameter ?: getter.extensionReceiverParameter - val receiver = Variable(receiverParameter!!.symbol, args[0].toState(receiverParameter.type)) + val receiverParameter = (getter.dispatchReceiverParameter ?: getter.extensionReceiverParameter)!! + val receiver = Variable(receiverParameter.symbol, args[0].toState(receiverParameter.getActualType())) return callInterceptor.interceptProxy(getter, listOf(receiver)) } @@ -48,10 +60,10 @@ internal class KMutableProperty1Proxy( override fun call(vararg args: Any?) { checkArguments(2, args.size) - val receiverParameter = setter.dispatchReceiverParameter ?: setter.extensionReceiverParameter - val receiver = Variable(receiverParameter!!.symbol, args[0].toState(receiverParameter.type)) + val receiverParameter = (setter.dispatchReceiverParameter ?: setter.extensionReceiverParameter)!! + val receiver = Variable(receiverParameter.symbol, args[0].toState(receiverParameter.getActualType())) val valueParameter = setter.valueParameters.single() - val value = Variable(valueParameter.symbol, args[1].toState(valueParameter.type)) + val value = Variable(valueParameter.symbol, args[1].toState(valueParameter.getActualType())) callInterceptor.interceptProxy(setter, listOf(receiver, value)) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/ReflectionState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/ReflectionState.kt index b886543e492..83c73bcb419 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/ReflectionState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/ReflectionState.kt @@ -42,16 +42,15 @@ internal abstract class ReflectionState : State { private fun renderReceivers(dispatchReceiver: IrType?, extensionReceiver: IrType?): String { return buildString { if (dispatchReceiver != null) { - append(dispatchReceiver.renderType()) - append(".") + append(dispatchReceiver.renderType()).append(".") } - val addParentheses = dispatchReceiver != null && extensionReceiver != null - if (addParentheses) append("(") + if (extensionReceiver != null) { - append(extensionReceiver.renderType()) - append(".") + val addParentheses = dispatchReceiver != null + if (addParentheses) append("(") + append(extensionReceiver.renderType()).append(".") + if (addParentheses) append(")") } - if (addParentheses) append(")") } } @@ -79,7 +78,12 @@ internal abstract class ReflectionState : State { } protected fun IrType.renderType(): String { - var renderedType = this.render() + var renderedType = this.render().replace(".", "") + if (renderedType.contains("', startIndex) + 1 + renderedType = renderedType.replaceRange(startIndex, lastTriangle, "get") + } do { val index = renderedType.indexOf(" of ") if (index == -1) break diff --git a/compiler/testData/ir/interpreter/reference/propertyReference.kt b/compiler/testData/ir/interpreter/reference/propertyReference.kt index 393b58f1ed4..19306c58784 100644 --- a/compiler/testData/ir/interpreter/reference/propertyReference.kt +++ b/compiler/testData/ir/interpreter/reference/propertyReference.kt @@ -23,3 +23,10 @@ const val mutablePropertyWithReceiverName = B(10)::b.name const val mutablePropertyWithReceiverGet = B(11)::b.get() const val mutablePropertyWithReceiverSet = B(12).apply { this::b.set(13) }.b const val mutablePropertyWithReceiverInvoke = B(14)::b.invoke() + +@CompileTimeCalculation +var T.bar : T + get() = this + set(value) { } + +const val barToString = String::bar.toString()