diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt index c6c40c91db8..a347762cc8c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt @@ -52,10 +52,13 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform } override final fun visitField(declaration: IrField): IrStatement { - val isDelegated = declaration.descriptor.isDelegated - if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) + val peek = scopeStack.peek() + val fieldDiffersFromProperty = peek == null || peek.scope.scopeOwner != declaration.descriptor + if (fieldDiffersFromProperty) + scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) val result = visitFieldNew(declaration) - if (isDelegated) scopeStack.pop() + if (fieldDiffersFromProperty) + scopeStack.pop() return result } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index 83005ae9187..c2591479d09 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -55,6 +55,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai when (memberDeclaration) { is IrFunction -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() + is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() else -> null } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index dbddb3a2952..b99d6c9a9ae 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -101,34 +101,35 @@ internal class SpecialDescriptorsFactory(val context: Context) { descriptor: FunctionDescriptor, bridgeDirections: Array) { val returnType = when (bridgeDirections[0]) { - BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!! - BridgeDirection.NOT_NEEDED -> descriptor.returnType + BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!! + BridgeDirection.NOT_NEEDED -> descriptor.returnType BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType } val extensionReceiverType = when (bridgeDirections[1]) { - BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type - BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type + BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type + BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType } val valueParameters = descriptor.valueParameters.mapIndexed { index, valueParameterDescriptor -> - when (bridgeDirections[index + 2]) { - BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor - BridgeDirection.NOT_NEEDED -> valueParameterDescriptor - BridgeDirection.FROM_VALUE_TYPE -> ValueParameterDescriptorImpl( - containingDeclaration = valueParameterDescriptor.containingDeclaration, - original = null, - index = index, - annotations = Annotations.EMPTY, - name = valueParameterDescriptor.name, - outType = context.builtIns.anyType, - declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(), - isCrossinline = valueParameterDescriptor.isCrossinline, - isNoinline = valueParameterDescriptor.isNoinline, - varargElementType = valueParameterDescriptor.varargElementType, - source = SourceElement.NO_SOURCE) - } + val outType = when (bridgeDirections[index + 2]) { + BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor.type + BridgeDirection.NOT_NEEDED -> valueParameterDescriptor.type + BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType + } + ValueParameterDescriptorImpl( + containingDeclaration = valueParameterDescriptor.containingDeclaration, + original = null, + index = index, + annotations = Annotations.EMPTY, + name = valueParameterDescriptor.name, + outType = outType, + declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(), + isCrossinline = valueParameterDescriptor.isCrossinline, + isNoinline = valueParameterDescriptor.isNoinline, + varargElementType = valueParameterDescriptor.varargElementType, + source = SourceElement.NO_SOURCE) } bridgeDescriptor.initialize( /* receiverParameterType = */ extensionReceiverType, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt index 3d9c13c4e6a..a73095141c5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt @@ -29,19 +29,17 @@ enum class KonanPhase(val description: String, /* ... */ LOWER("IR Lowering"), /* ... ... */ LOWER_INLINE("Functions inlining"), /* ... ... ... */ DESERIALIZER("Deserialize inline bodies"), - /* ... ... */ LOWER_INTEROP("Interop lowering"), /* ... ... */ LOWER_ENUMS("Enum classes lowering"), /* ... ... */ LOWER_DELEGATION("Delegation lowering"), /* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS), /* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS), - /* ... ... */ LOWER_CALLABLES("Callable references Lowering", - LOWER_INTEROP, LOWER_INITIALIZERS, LOWER_DELEGATION), - /* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES), /* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES), + /* ... ... */ LOWER_INTEROP("Interop lowering", LOWER_LOCAL_FUNCTIONS), + /* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS), + /* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES), /* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS), /* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC), - /* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", - LOWER_TAILREC, LOWER_ENUMS), + /* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", LOWER_TAILREC, LOWER_ENUMS), /* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", LOWER_DEFAULT_PARAMETER_EXTENT), /* ... ... */ LOWER_LATEINIT("Lateinit properties lowering"), /* ... ... */ LOWER_BUILTIN_OPERATORS("BuiltIn Operators Lowering", LOWER_DEFAULT_PARAMETER_EXTENT, LOWER_LATEINIT), diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ValueTypes.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ValueTypes.kt index 6a7d49ba983..2385b9a3bf0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ValueTypes.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ValueTypes.kt @@ -40,7 +40,6 @@ enum class ValueType(val classFqName: FqNameUnsafe, val isNullable: Boolean = fa FLOAT(KotlinBuiltIns.FQ_NAMES._float), DOUBLE(KotlinBuiltIns.FQ_NAMES._double), - UNBOUND_CALLABLE_REFERENCE(FqNameUnsafe("konan.internal.UnboundCallableReference")), NATIVE_PTR(KonanBuiltIns.FqNames.nativePtr), NATIVE_POINTED(InteropBuiltIns.FqNames.nativePointed, isNullable = true), diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index c6b5b8300d2..0fb8586ce82 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -137,8 +137,6 @@ internal fun KonanBuiltIns.getKonanInternalFunctions(name: String): List LLVMFloatType() ValueType.DOUBLE -> LLVMDoubleType() - ValueType.UNBOUND_CALLABLE_REFERENCE, ValueType.NATIVE_PTR, ValueType.NATIVE_POINTED, ValueType.C_POINTER -> int8TypePtr }!! } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 30cc2bcaf2f..0272b2cf27e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -689,7 +689,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid is IrBreak -> return evaluateBreak (value) is IrContinue -> return evaluateContinue (value) is IrGetObjectValue -> return evaluateGetObjectValue (value) - is IrCallableReference -> return evaluateCallableReference (value) + is IrFunctionReference -> return evaluateFunctionReference (value) is IrSuspendableExpression -> return evaluateSuspendableExpression (value) is IrSuspensionPoint -> return evaluateSuspensionPoint (value) @@ -1744,17 +1744,16 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid //-------------------------------------------------------------------------// - private fun evaluateCallableReference(expression: IrCallableReference): LLVMValueRef { + private fun evaluateFunctionReference(expression: IrFunctionReference): LLVMValueRef { // TODO: consider creating separate IR element for pointer to function. - assert (expression.type.isUnboundCallableReference() || - TypeUtils.getClassDescriptor(expression.type) == context.interopBuiltIns.cPointer) + assert (TypeUtils.getClassDescriptor(expression.type) == context.interopBuiltIns.cPointer) assert (expression.getArguments().isEmpty()) val descriptor = expression.descriptor assert (descriptor.dispatchReceiverParameter == null) - val entry = codegen.functionEntryPointAddress(descriptor as FunctionDescriptor) + val entry = codegen.functionEntryPointAddress(descriptor) return entry } @@ -1822,10 +1821,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid val argsWithContinuationIfNeeded = if (descriptor.isSuspend) args + getContinuation() else args - if (descriptor.isFunctionInvoke) { - return evaluateFunctionInvoke(descriptor, argsWithContinuationIfNeeded, resultLifetime) - } - if (descriptor.isIntrinsic) { return evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded) } @@ -1840,40 +1835,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid //-------------------------------------------------------------------------// - private val functionImplUnboundRefGetter by lazy { - context.builtIns.getKonanInternalClass("FunctionImpl") - .unsubstitutedMemberScope.getContributedDescriptors() - .filterIsInstance() - .single { it.name.asString() == "unboundRef" } - .getter!! - } - - private fun evaluateFunctionInvoke(descriptor: FunctionDescriptor, - args: List, resultLifetime: Lifetime): LLVMValueRef { - - // Note: the whole function code below is written in the assumption that - // `invoke` method receiver is passed as first argument. - - val functionImpl = args[0] // Instance of `konan.internal.FunctionImpl`. - - // `functionImpl.unboundRef` is the pointer to (static) function of type - // `(FunctionImpl, Arg_1, ..., Arg_n): Ret`. See [CallableReferenceLowering] for details. - // LLVM type for such function is equal to type for `FunctionImpl.invoke(Arg_1, ..., Arg_n): Ret`. - // So we can use the latter for simplicity: - val unboundRefType = codegen.getLlvmFunctionType(descriptor) - - // Get `functionImpl.unboundRef`: - val unboundRef = evaluateSimpleFunctionCall(functionImplUnboundRefGetter, - listOf(functionImpl), Lifetime.IRRELEVANT /* unboundRef isn't managed reference */) - - // Cast `functionImpl.unboundRef` to pointer to function: - val entryPtr = codegen.bitcast(pointerType(unboundRefType), unboundRef, "entry") - - return call(descriptor, entryPtr, args, resultLifetime) - } - - //-------------------------------------------------------------------------// - private fun evaluateSimpleFunctionCall( descriptor: FunctionDescriptor, args: List, resultLifetime: Lifetime, superClass: ClassDescriptor? = null): LLVMValueRef { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt index 7cee6d6e7a5..1c3e2b74669 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt @@ -18,256 +18,502 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters -import org.jetbrains.kotlin.backend.common.lower.createIrBuilder -import org.jetbrains.kotlin.backend.konan.KonanBackendContext +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionOrKFunctionType +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor +import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.descriptors.impl.* +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.expressions.IrCallableReference +import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionReference -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl -import org.jetbrains.kotlin.ir.util.addArguments +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.getArguments -import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeProjectionImpl +import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.replace +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.util.transformFlat +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -/** - * This lowering pass lowers all [IrCallableReference]s to unbound ones. - */ -internal class CallableReferenceLowering(val context: KonanBackendContext) : DeclarationContainerLoweringPass { +internal class CallableReferenceLowering(val context: Context): DeclarationContainerLoweringPass { - var callableReferenceCount = 0 + private var functionReferenceCount = 0 override fun lower(irDeclarationContainer: IrDeclarationContainer) { irDeclarationContainer.declarations.transformFlat { declaration -> if (declaration !is IrDeclarationContainer) - lowerCallableReferences(this, irDeclarationContainer, declaration) + lowerFunctionReferences(irDeclarationContainer, declaration) else null } } -} -/** - * Replaces all callable references in the function body to unbound ones. - * Returns the list of this function and all created ones. - */ -private fun lowerCallableReferences(lower: CallableReferenceLowering, - irDeclarationContainer: IrDeclarationContainer, - declaration: IrDeclaration): List { - val containingDeclaration = when (irDeclarationContainer) { - is IrClass -> irDeclarationContainer.descriptor - is IrFile -> irDeclarationContainer.packageFragmentDescriptor - else -> throw AssertionError("Unexpected declaration container: $irDeclarationContainer") - } - val transformer = CallableReferencesUnbinder(lower, containingDeclaration) - declaration.transformChildrenVoid(transformer) - return listOf(declaration) + transformer.createdFunctions -} - -private object DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE : - IrDeclarationOriginImpl("FUNCTION_FOR_CALLABLE_REFERENCE") - -/** - * Replaces all callable references in the function body to unbound ones. - * Adds all created functions to [createdFunctions]. - */ -private class CallableReferencesUnbinder(val lower: CallableReferenceLowering, - val containingDeclaration: DeclarationDescriptor) : IrElementTransformerVoid() { - - val createdFunctions = mutableListOf() - - private val builtIns = lower.context.builtIns - - override fun visitElement(element: IrElement): IrElement { - return super.visitElement(element) - } - - private val unboundCallableReferenceType by lazy { - builtIns.getKonanInternalClass("UnboundCallableReference").defaultType - } - - private val simpleFunctionImplClass by lazy { - builtIns.getKonanInternalClass("SimpleFunctionImpl") - } - - private val simpleFunctionImplBoundArgsGetter by lazy { - simpleFunctionImplClass.defaultType.memberScope.getContributedDescriptors() - .filterIsInstance() - .single { it.name.asString() == "boundArgs" } - .getter!! - } - - override fun visitClass(declaration: IrClass): IrStatement { - // Class is a declaration container - it will be visited by the main visitor (CallableReferenceLowering). - return declaration - } - - override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { - expression.transformChildrenVoid(this) - if (!expression.type.isFunctionOrKFunctionType) { - // Not a subject of this lowering. - return expression + private fun lowerFunctionReferences(irDeclarationContainer: IrDeclarationContainer, + declaration: IrDeclaration): List { + val containingDeclaration = when (irDeclarationContainer) { + is IrClass -> irDeclarationContainer.descriptor + is IrFile -> irDeclarationContainer.packageFragmentDescriptor + else -> throw AssertionError("Unexpected declaration container: $irDeclarationContainer") } + val createdClasses = mutableListOf() + declaration.transformChildrenVoid(object: IrElementTransformerVoid() { - val descriptor = expression.descriptor - val boundArgs = expression.getArguments() - val boundParams = boundArgs.map { it.first } - - val allParams = descriptor.explicitParameters - val unboundParams = allParams - boundParams - - val startOffset = expression.startOffset - val endOffset = expression.endOffset - - // The code below creates a call to `SimpleFunctionImpl` constructor which creates the object implementing - // the function type. - - // Create the function to be used as `unboundRef` of `SimpleFunctionImpl`: - val newFunction = createSimpleFunctionImplTarget(descriptor, unboundParams, boundParams, startOffset, endOffset) - - createdFunctions.add(newFunction) - - // Create the call to constructor and its arguments: - - val unboundRef = IrFunctionReferenceImpl(startOffset, endOffset, - unboundCallableReferenceType, newFunction.descriptor, null) - val simpleFunctionImplClassConstructor = simpleFunctionImplClass.unsubstitutedPrimaryConstructor!! - - val boundArgsVarargParam = simpleFunctionImplClassConstructor.valueParameters[1] - val boundArgsVararg = IrVarargImpl( - startOffset, endOffset, - boundArgsVarargParam.type, - boundArgsVarargParam.varargElementType!!, - boundArgs.map { it.second } - ) - - return IrCallImpl(startOffset, endOffset, simpleFunctionImplClassConstructor).apply { - putValueArgument(0, unboundRef) - putValueArgument(1, boundArgsVararg) - } - } - - /** - * For given function [descriptor] creates the function which calls [descriptor] but - * takes all [boundParams] packed into `SimpleFunctionImpl` (and all [unboundParams] as is). - */ - private fun createSimpleFunctionImplTarget(descriptor: FunctionDescriptor, - unboundParams: List, - boundParams: List, - startOffset: Int, endOffset: Int): IrFunctionImpl { - - // Create new function descriptor: - val newDescriptor = createSimpleFunctionImplTargetDescriptor(descriptor, unboundParams) - - val builder = lower.context.createIrBuilder(newDescriptor) - val blockBody = builder.irBlockBody(startOffset, endOffset) { - val boundArgsGet = irCall(simpleFunctionImplBoundArgsGetter).apply { - dispatchReceiver = irGet(newDescriptor.valueParameters[0]) + override fun visitClass(declaration: IrClass): IrStatement { + // Class is a declaration container - it will be visited by the main visitor (CallableReferenceLowering). + return declaration } - +irLet(boundArgsGet) { boundArgs -> - val arrayGet = boundArgs.type.memberScope.getContributedDescriptors() - .filterIsInstance().single { it.name.asString() == "get" } + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + expression.transformChildrenVoid(this) - // TODO: some handling for type parameters is probably required here. - - // Call to old function from new function: - val call = irCall(descriptor).apply { - // unboundParams are received as all new function parameters except first: - val newUnboundParams = newDescriptor.valueParameters.drop(1) - assert (unboundParams.size == newUnboundParams.size) - addArguments(unboundParams.mapIndexed { index, param -> - param to irGet(newUnboundParams[index]) - }) - - // boundParams are received in `SimpleFunctionImpl.boundArgs`: - addArguments(boundParams.mapIndexed { index, param -> - param to irCall(arrayGet).apply { - dispatchReceiver = irGet(boundArgs) - putValueArgument(0, irInt(index)) - } - }) + if (!expression.type.isFunctionOrKFunctionType) { + // Not a subject of this lowering. + return expression } - irReturn(call) + val loweredFunctionReference = FunctionReferenceBuilder(containingDeclaration, expression).build() + createdClasses += loweredFunctionReference.functionReferenceClass + return IrCallImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + calleeDescriptor = loweredFunctionReference.functionReferenceConstructorDescriptor).apply { + expression.getArguments().forEachIndexed { index, argument -> + putValueArgument(index, argument.second) + } + } + } + }) + return listOf(declaration) + createdClasses + } + + private abstract class DescriptorWithIrBuilder { + + protected abstract fun buildDescriptor(): D + + protected open fun doInitialize() {} + + protected abstract fun buildIr(): B + + val descriptor by lazy { buildDescriptor() } + + private val builtIr by lazy { buildIr() } + private var initialized: Boolean = false + + fun initialize() { + doInitialize() + initialized = true + } + + val ir: B + get() { + if (!initialized) + throw Error("Access to IR before initialization") + return builtIr + } + } + + private class BuiltFunctionReference(val functionReferenceClass: IrClass, + val functionReferenceConstructorDescriptor: ClassConstructorDescriptor) + + private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor, + val functionReference: IrFunctionReference) { + + private val functionDescriptor = functionReference.descriptor + private val functionParameters = functionDescriptor.explicitParameters + private val boundFunctionParameters = functionReference.getArguments().map { it.first } + private val unboundFunctionParameters = functionParameters - boundFunctionParameters + + private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl + private lateinit var argumentToPropertiesMap: Map + private val functionReferenceMembers = mutableListOf() + + private fun KotlinType.replace(types: List) = this.replace(types.map(::TypeProjectionImpl)) + + private val kFunctionImplClassDescriptor = context.builtIns.getKonanInternalClass("KFunctionImpl") + + fun build(): BuiltFunctionReference { + val startOffset = functionReference.startOffset + val endOffset = functionReference.endOffset + + val superTypes = mutableListOf( + kFunctionImplClassDescriptor.defaultType.replace(listOf(functionDescriptor.returnType!!)) + ) + var suspendFunctionClassDescriptor: ClassDescriptor? = null + val functionClassDescriptor = context.reflectionTypes.getKFunction(unboundFunctionParameters.size) + val types = unboundFunctionParameters.map { it.type } + functionDescriptor.returnType!! + superTypes += functionClassDescriptor.defaultType.replace(types) + + functionReferenceClassDescriptor = ClassDescriptorImpl( + /* containingDeclaration = */ containingDeclaration, + /* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName, + /* modality = */ Modality.FINAL, + /* kind = */ ClassKind.CLASS, + /* superTypes = */ superTypes, + /* source = */ SourceElement.NO_SOURCE, + /* isExternal = */ false + ) + val constructorBuilder = createConstructorBuilder() + + val typeSubstitutor = TypeSubstitutor.create( + functionClassDescriptor.declaredTypeParameters + .withIndex() + .associateBy({ it.value.typeConstructor }, { TypeProjectionImpl(types[it.index]) }) + ) + val invokeFunctionDescriptor = functionClassDescriptor.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single().substitute(typeSubstitutor)!! + val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionDescriptor) + + val inheritedKFunctionImpl = kFunctionImplClassDescriptor.unsubstitutedMemberScope + .getContributedDescriptors() + .map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) } + .filterNotNull() + val contributedDescriptors = ( + inheritedKFunctionImpl + invokeMethodBuilder.descriptor + ).toList() + functionReferenceClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.descriptor), null) + + constructorBuilder.initialize() + functionReferenceMembers.add(constructorBuilder.ir) + + invokeMethodBuilder.initialize() + functionReferenceMembers.add(invokeMethodBuilder.ir) + + val functionReferenceClass = IrClassImpl( + startOffset = startOffset, + endOffset = endOffset, + origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + descriptor = functionReferenceClassDescriptor, + members = functionReferenceMembers + ) + + functionReferenceClass.createParameterDeclarations() + + return BuiltFunctionReference(functionReferenceClass, constructorBuilder.descriptor) + } + + private fun ParameterDescriptor.copyAsValueParameter(newOwner: CallableDescriptor, index: Int) + = when (this) { + is ValueParameterDescriptor -> this.copy(newOwner, name, index) + is ReceiverParameterDescriptor -> ValueParameterDescriptorImpl( + containingDeclaration = newOwner, + original = null, + index = index, + annotations = annotations, + name = name, + outType = type, + declaresDefaultValue = false, + isCrossinline = false, + isNoinline = false, + varargElementType = null, + source = source + ) + else -> throw Error("Unexpected parameter descriptor: $this") + } + + private fun createConstructorBuilder() + = object : DescriptorWithIrBuilder() { + + private val kFunctionImplConstructorDescriptor = kFunctionImplClassDescriptor.constructors.single() + private lateinit var constructorParameters: List + + override fun buildDescriptor(): ClassConstructorDescriptorImpl { + return ClassConstructorDescriptorImpl.create( + /* containingDeclaration = */ functionReferenceClassDescriptor, + /* annotations = */ Annotations.EMPTY, + /* isPrimary = */ false, + /* source = */ SourceElement.NO_SOURCE + ) + } + + override fun doInitialize() { + constructorParameters = boundFunctionParameters.mapIndexed { index, parameter -> + parameter.copyAsValueParameter(descriptor, index) + } + descriptor.initialize(constructorParameters, Visibilities.PUBLIC) + descriptor.returnType = functionReferenceClassDescriptor.defaultType + } + + override fun buildIr(): IrConstructor { + argumentToPropertiesMap = boundFunctionParameters.associate { + it to buildPropertyWithBackingField(it.name, it.type, false) + } + + val startOffset = functionReference.startOffset + val endOffset = functionReference.endOffset + val irBuilder = context.createIrBuilder(descriptor, startOffset, endOffset) + return IrConstructorImpl( + startOffset = startOffset, + endOffset = endOffset, + origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + descriptor = descriptor).apply { + + createParameterDeclarations() + + body = irBuilder.irBlockBody { + +IrDelegatingConstructorCallImpl(startOffset, endOffset, kFunctionImplConstructorDescriptor).apply { + val name = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, + IrConstKind.String, functionDescriptor.name.asString()) + putValueArgument(0, name) + val fqName = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String, + functionDescriptor.fullName) + putValueArgument(1, fqName) + val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, + boundFunctionParameters.isNotEmpty()) + putValueArgument(2, bound) + val needReceiver = boundFunctionParameters.singleOrNull() is ReceiverParameterDescriptor + val receiver = if (needReceiver) irGet(constructorParameters.single()) else irNull() + putValueArgument(3, receiver) + } + +IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClassDescriptor) + // Save all arguments to fields. + boundFunctionParameters.forEachIndexed { index, parameter -> + +irSetField(irThis(), argumentToPropertiesMap[parameter]!!, irGet(constructorParameters[index])) + } + } + } } } - val newFunction = IrFunctionImpl( - startOffset, endOffset, DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE, - newDescriptor, - blockBody - ) + // TODO: what about private package level functions? + private val DeclarationDescriptor.fullName: String + get() { + return when (this) { + is PackageFragmentDescriptor -> fqNameSafe.asString() + is ClassDescriptor -> containingDeclaration.fullName + "." + fqNameSafe + is FunctionDescriptor -> containingDeclaration.fullName + "." + functionName + is PropertyDescriptor -> containingDeclaration.fullName + "." + fqNameSafe + else -> TODO("$this") + } + } - newFunction.createParameterDeclarations() + private fun createInvokeMethodBuilder(functionInvokeFunctionDescriptor: FunctionDescriptor) + = object : DescriptorWithIrBuilder() { - return newFunction - } + override fun buildDescriptor() = SimpleFunctionDescriptorImpl.create( + /* containingDeclaration = */ functionReferenceClassDescriptor, + /* annotations = */ Annotations.EMPTY, + /* name = */ Name.identifier("invoke"), + /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, + /* source = */ SourceElement.NO_SOURCE) - /** - * Creates descriptor for [createSimpleFunctionImplTarget]. - */ - private fun createSimpleFunctionImplTargetDescriptor(descriptor: CallableDescriptor, - unboundParams: List): FunctionDescriptor { + override fun doInitialize() { + val valueParameters = functionInvokeFunctionDescriptor.valueParameters + .map { it.copyAsValueParameter(this.descriptor, it.index) } - val newName = Name.identifier("${descriptor.name}\$bound-${lower.callableReferenceCount++}") + this.descriptor.initialize( + /* receiverParameterType = */ null, + /* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter, + /* typeParameters = */ emptyList(), + /* unsubstitutedValueParameters = */ valueParameters, + /* unsubstitutedReturnType = */ functionInvokeFunctionDescriptor.returnType, + /* modality = */ Modality.FINAL, + /* visibility = */ Visibilities.PRIVATE).apply { + overriddenDescriptors += functionInvokeFunctionDescriptor + } + } - val newDescriptor = SimpleFunctionDescriptorImpl.create( - containingDeclaration, Annotations.EMPTY, - newName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE) + override fun buildIr(): IrFunction { + val startOffset = functionReference.startOffset + val endOffset = functionReference.endOffset + val ourDescriptor = this.descriptor + val irBuilder = context.createIrBuilder(this.descriptor, startOffset, endOffset) + return IrFunctionImpl( + startOffset = startOffset, + endOffset = endOffset, + origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + descriptor = this.descriptor).apply { - val simpleFunctionImplType = simpleFunctionImplClass.defaultType + createParameterDeclarations() - // Map each unbound param of original function to parameter of new function. - val newUnboundParams = unboundParams.mapIndexed { index, param -> - ValueParameterDescriptorImpl( - containingDeclaration = newDescriptor, - original = null, - index = index + 1, - annotations = Annotations.EMPTY, - name = param.name, - outType = builtIns.nullableAnyType, // Use erased type. - declaresDefaultValue = false, - isCrossinline = false, isNoinline = false, - varargElementType = null, - source = SourceElement.NO_SOURCE) + body = irBuilder.irBlockBody(startOffset, endOffset) { + +irReturn( + irCall(functionReference.descriptor).apply { + var unboundIndex = 0 + val unboundArgsSet = unboundFunctionParameters.toSet() + functionParameters.forEach { + val argument = if (unboundArgsSet.contains(it)) + irGet(ourDescriptor.valueParameters[unboundIndex++]) + else + irGet(irThis(), argumentToPropertiesMap[it]!!) + when (it) { + functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument + functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument + else -> putValueArgument((it as ValueParameterDescriptor).index, argument) + } + } + assert(unboundIndex == ourDescriptor.valueParameters.size, + { "Not all arguments of are used" }) + } + ) + } + } + } } - // `: SimpleFunctionImpl` - val functionParameter = ValueParameterDescriptorImpl( - containingDeclaration = newDescriptor, - original = null, - index = 0, - annotations = Annotations.EMPTY, - name = Name.special(""), - outType = simpleFunctionImplType, - declaresDefaultValue = false, - isCrossinline = false, isNoinline = false, - varargElementType = null, - source = SourceElement.NO_SOURCE) + private fun createPropertyGetterBuilder(propertyDescriptor: PropertyDescriptor, type: KotlinType) + = object : DescriptorWithIrBuilder() { - val newValueParameters = listOf(functionParameter) + newUnboundParams + override fun buildDescriptor() = PropertyGetterDescriptorImpl( + /* correspondingProperty = */ propertyDescriptor, + /* annotations = */ Annotations.EMPTY, + /* modality = */ Modality.FINAL, + /* visibility = */ Visibilities.PRIVATE, + /* isDefault = */ false, + /* isExternal = */ false, + /* isInline = */ false, + /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, + /* original = */ null, + /* source = */ SourceElement.NO_SOURCE + ) - val newReturnType = builtIns.nullableAnyType // Use erased type. + override fun doInitialize() { + descriptor.apply { + initialize(type) + } + } - newDescriptor.initialize(null, null, descriptor.typeParameters, newValueParameters, - newReturnType, Modality.FINAL, Visibilities.PRIVATE) + override fun buildIr() = IrFunctionImpl( + startOffset = functionReference.startOffset, + endOffset = functionReference.endOffset, + origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + descriptor = descriptor).apply { - return newDescriptor + createParameterDeclarations() + + body = context.createIrBuilder(descriptor, startOffset, endOffset).irBlockBody { + +irReturn(irGetField(irThis(), propertyDescriptor)) + } + } + } + + private fun createPropertySetterBuilder(propertyDescriptor: PropertyDescriptor, type: KotlinType) + = object : DescriptorWithIrBuilder() { + + override fun buildDescriptor() = PropertySetterDescriptorImpl( + /* correspondingProperty = */ propertyDescriptor, + /* annotations = */ Annotations.EMPTY, + /* modality = */ Modality.FINAL, + /* visibility = */ Visibilities.PRIVATE, + /* isDefault = */ false, + /* isExternal = */ false, + /* isInline = */ false, + /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, + /* original = */ null, + /* source = */ SourceElement.NO_SOURCE + ) + + lateinit var valueParameterDescriptor: ValueParameterDescriptor + + override fun doInitialize() { + descriptor.apply { + valueParameterDescriptor = ValueParameterDescriptorImpl( + containingDeclaration = this, + original = null, + index = 0, + annotations = Annotations.EMPTY, + name = Name.identifier("value"), + outType = type, + declaresDefaultValue = false, + isCrossinline = false, + isNoinline = false, + varargElementType = null, + source = SourceElement.NO_SOURCE + ) + + initialize(valueParameterDescriptor) + } + } + + override fun buildIr() = IrFunctionImpl( + startOffset = functionReference.startOffset, + endOffset = functionReference.endOffset, + origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + descriptor = descriptor).apply { + + createParameterDeclarations() + + body = context.createIrBuilder(descriptor, startOffset, endOffset).irBlockBody { + +irSetField(irThis(), propertyDescriptor, irGet(valueParameterDescriptor)) + } + } + } + + private fun createPropertyWithBackingFieldBuilder(name: Name, type: KotlinType, isMutable: Boolean) + = object : DescriptorWithIrBuilder() { + + private lateinit var getterBuilder: DescriptorWithIrBuilder + private var setterBuilder: DescriptorWithIrBuilder? = null + + override fun buildDescriptor() = PropertyDescriptorImpl.create( + /* containingDeclaration = */ functionReferenceClassDescriptor, + /* annotations = */ Annotations.EMPTY, + /* modality = */ Modality.FINAL, + /* visibility = */ Visibilities.PRIVATE, + /* isVar = */ isMutable, + /* name = */ name, + /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, + /* source = */ SourceElement.NO_SOURCE, + /* lateInit = */ false, + /* isConst = */ false, + /* isHeader = */ false, + /* isImpl = */ false, + /* isExternal = */ false, + /* isDelegated = */ false) + + override fun doInitialize() { + getterBuilder = createPropertyGetterBuilder(descriptor, type).apply { initialize() } + if (isMutable) + setterBuilder = createPropertySetterBuilder(descriptor, type).apply { initialize() } + descriptor.initialize(getterBuilder.descriptor, setterBuilder?.descriptor) + val receiverType: KotlinType? = null + descriptor.setType(type, emptyList(), functionReferenceClassDescriptor.thisAsReceiverParameter, receiverType) + } + + override fun buildIr(): IrProperty { + val startOffset = functionReference.startOffset + val endOffset = functionReference.endOffset + val backingField = IrFieldImpl( + startOffset = startOffset, + endOffset = endOffset, + origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + descriptor = descriptor) + return IrPropertyImpl( + startOffset = startOffset, + endOffset = endOffset, + origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + isDelegated = false, + descriptor = descriptor, + backingField = backingField, + getter = getterBuilder.ir, + setter = setterBuilder?.ir) + } + } + + private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): PropertyDescriptor { + val propertyBuilder = createPropertyWithBackingFieldBuilder(name, type, isMutable).apply { initialize() } + + functionReferenceMembers.add(propertyBuilder.ir) + return propertyBuilder.descriptor + } + + private object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL : + IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL") } } diff --git a/runtime/src/main/kotlin/konan/internal/Function.kt b/runtime/src/main/kotlin/konan/internal/Function.kt deleted file mode 100644 index 370eb8123e9..00000000000 --- a/runtime/src/main/kotlin/konan/internal/Function.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package konan.internal - -/** - * Represents the reference to callable without any bound arguments. - * It is supposed to be represented at runtime as native pointer to code. - * - * TODO: it seems to be very closely related to native interop types. - */ -abstract class UnboundCallableReference internal constructor() - -/** - * Values of function types are represented at runtime as instances of this class (and its subclasses). - * - * [FunctionImpl] is a reference to callable with itself as single bound argument, - * i.e. when calling this function with arguments `args`, [unboundRef] is called with arguments `(this, *args)`. - * So the instance is supposed to contain all implicit (bound) arguments of target function, e.g. captured values. - */ -open class FunctionImpl(val unboundRef: UnboundCallableReference) - -/** - * Simple [FunctionImpl] implementation: all bound arguments of target callable to be placed into [boundArgs]. - */ -class SimpleFunctionImpl(unboundRef: UnboundCallableReference, vararg val boundArgs: Any?) : FunctionImpl(unboundRef) \ No newline at end of file diff --git a/runtime/src/main/kotlin/konan/internal/KFunctionImpl.kt b/runtime/src/main/kotlin/konan/internal/KFunctionImpl.kt new file mode 100644 index 00000000000..0467a8e6928 --- /dev/null +++ b/runtime/src/main/kotlin/konan/internal/KFunctionImpl.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package konan.internal + +import kotlin.reflect.KFunction + +@FixmeReflection +open class KFunctionImpl(override val name: String, val fqName: String, val bound: Boolean, val receiver: Any?): KFunction { + override fun equals(other: Any?): Boolean { + if (other !is KFunctionImpl<*>) return false + return fqName == other.fqName && bound == other.bound && receiver == other.receiver + } + + override fun hashCode(): Int { + return (fqName.hashCode() * 31 + if (bound) 1 else 0) * 31 + receiver.hashCode() + } + + override fun toString(): String { + return fqName + } +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt b/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt index 81ca27a0131..267d91a956c 100644 --- a/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt +++ b/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt @@ -65,11 +65,11 @@ public interface KProperty : KCallable { // @FixmeReflection -public interface KProperty0 : kotlin.reflect.KProperty/* TODO , (T) -> R*/ { +public interface KProperty0 : kotlin.reflect.KProperty, () -> R { // public abstract val getter: kotlin.reflect.KProperty1.Getter public abstract fun get(): R - public abstract operator fun invoke(): R + public override abstract operator fun invoke(): R // @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any? // @@ -78,11 +78,11 @@ public interface KProperty0 : kotlin.reflect.KProperty/* TODO , (T) -> } @FixmeReflection -public interface KProperty1 : kotlin.reflect.KProperty/* TODO , (T) -> R*/ { +public interface KProperty1 : kotlin.reflect.KProperty, (T) -> R { // public abstract val getter: kotlin.reflect.KProperty1.Getter public abstract fun get(receiver: T): R - public abstract operator fun invoke(receiver: T): R + public override abstract operator fun invoke(receiver: T): R // @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any? // @@ -91,11 +91,11 @@ public interface KProperty1 : kotlin.reflect.KProperty/* TODO , (T) } @FixmeReflection -public interface KProperty2 : kotlin.reflect.KProperty/* TODO , (T) -> R*/ { +public interface KProperty2 : kotlin.reflect.KProperty, (T1, T2) -> R { // public abstract val getter: kotlin.reflect.KProperty1.Getter public abstract fun get(receiver1: T1, receiver2: T2): R - public abstract operator fun invoke(receiver1: T1, receiver2: T2): R + public override abstract operator fun invoke(receiver1: T1, receiver2: T2): R // @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any? //