From ec0842c0f427e44e30be0f6ef383f9e7c1e1c4fa Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Thu, 15 Nov 2018 00:20:47 +0300 Subject: [PATCH] Remove descriptors from CallableReferenceLowering --- .../kotlin/backend/common/ir/IrUtils.kt | 30 +- .../common/lower/LocalDeclarationsLowering.kt | 11 +- .../jetbrains/kotlin/ir/util/IrTypeUtils.kt | 2 +- .../kotlin/backend/jvm/JvmBackendContext.kt | 6 + .../kotlin/backend/jvm/JvmLoweringPhases.kt | 6 +- .../jvm/lower/CallableReferenceLowering.kt | 1041 +++++++---------- .../backend/jvm/lower/FileClassLowering.kt | 3 +- .../ir/declarations/IrDeclarationOrigin.kt | 3 +- .../kotlin/ir/declarations/IrField.kt | 3 +- .../ir/util/DeepCopyIrTreeWithSymbols.kt | 7 +- .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 3 + 11 files changed, 494 insertions(+), 621 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt index edc5bcdf428..a94408f4a58 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt @@ -16,9 +16,11 @@ package org.jetbrains.kotlin.backend.common.ir +import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedReceiverParameterDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor @@ -41,10 +43,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl -import org.jetbrains.kotlin.ir.types.IrSimpleType -import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.IrTypeProjection -import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor @@ -354,7 +353,7 @@ fun Scope.createTemporaryVariableWithWrappedDescriptor( nameHint: String? = null, isMutable: Boolean = false, origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE): IrVariable { - + val descriptor = WrappedVariableDescriptor() return createTemporaryVariableWithGivenDescriptor( irExpression, nameHint, isMutable, origin, descriptor @@ -362,3 +361,24 @@ fun Scope.createTemporaryVariableWithWrappedDescriptor( } val IrFunction.isOverridable: Boolean get() = this is IrSimpleFunction && this.isOverridable + +fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() { + val thisReceiverDescriptor = WrappedReceiverParameterDescriptor() + thisReceiver = IrValueParameterImpl( + startOffset, endOffset, + IrDeclarationOrigin.INSTANCE_RECEIVER, + IrValueParameterSymbolImpl(thisReceiverDescriptor), + Name.identifier(""), + index = -1, + type = this.symbol.typeWith(this.typeParameters.map { it.defaultType }), + varargElementType = null, + isCrossinline = false, + isNoinline = false + ).also { valueParameter -> + thisReceiverDescriptor.bind(valueParameter) + valueParameter.parent = this + } + + assert(typeParameters.isEmpty()) + assert(descriptor.declaredTypeParameters.isEmpty()) +} diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index 804d5e158ca..06c7c80eed1 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -31,12 +31,8 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.name.NameUtils import java.util.* interface LocalNameProvider { @@ -769,6 +765,11 @@ class LocalDeclarationsLowering( val localClassContext = LocalClassContext(declaration) localClasses[declaration] = localClassContext } + + override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) { + // Getter and setter of local delegated properties are special generated functions and don't have closure. + declaration.delegate.initializer?.acceptVoid(this) + } }) } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt index 8634f8fe976..1f43f76c472 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.DFS val kotlinPackageFqn = FqName.fromSegments(listOf("kotlin")) -val kotlinReflectionPackageFqn = kotlinPackageFqn.child(Name.identifier("reflection")) +val kotlinReflectionPackageFqn = kotlinPackageFqn.child(Name.identifier("reflect")) val kotlinCoroutinesPackageFqn = kotlinPackageFqn.child(Name.identifier("coroutines")) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index fc41fd280c9..cada69f681a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -76,6 +76,10 @@ class JvmBackendContext( return find(state.module.getPackage(fqName.parent()).memberScope, fqName.shortName()) } + fun getIrClass(fqName: FqName): IrClassSymbol { + return ir.symbols.externalSymbolTable.referenceClass(getClass(fqName)) + } + override fun getInternalFunctions(name: String): List { return when (name) { "ThrowUninitializedPropertyAccessException" -> @@ -151,6 +155,8 @@ class JvmBackendContext( ) val lambdaClass = calc { symbolTable.referenceClass(context.getInternalClass("Lambda")) } + + fun getKFunction(parameterCount: Int) = symbolTable.referenceClass(reflectionTypes.getKFunction(parameterCount)) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt index 49e18ca5629..6b082563d48 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt @@ -11,8 +11,8 @@ import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.makePhase import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.jvm.lower.* -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.name.NameUtils @@ -108,8 +108,8 @@ private val SharedVariablesPhase = makeJvmPhase( private val LocalDeclarationsPhase = makeJvmPhase( { context, data -> LocalDeclarationsLowering(context, object : LocalNameProvider { - override fun localName(descriptor: DeclarationDescriptor): String = - NameUtils.sanitizeAsJavaIdentifier(super.localName(descriptor)) + override fun localName(declaration: IrDeclarationWithName): String = + NameUtils.sanitizeAsJavaIdentifier(super.localName(declaration)) }, Visibilities.PUBLIC, true).lower(data) }, name = "JvmLocalDeclarations", diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt index 7536e6b56bc..4ccb08351b6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt @@ -19,20 +19,13 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.descriptors.* -import org.jetbrains.kotlin.backend.common.ir.createFakeOverrideDescriptor +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.lower.* -import org.jetbrains.kotlin.backend.common.makePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.backend.jvm.codegen.isInlineCall import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression -import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen -import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* @@ -40,9 +33,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection @@ -51,13 +42,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.inline.InlineUtil -import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance -import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type //Hack implementation to support CR java types in lower @@ -78,11 +63,11 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { override fun visitCall(expression: IrCall): IrExpression { - val descriptor = expression.descriptor - if (descriptor.isInlineCall(context.state)) { + val callee = expression.symbol.owner + if (callee.isInlineFunction(context)) { //TODO: more wise filtering - descriptor.valueParameters.forEach { valueParameter -> - if (InlineUtil.isInlineParameter(valueParameter)) { + callee.valueParameters.forEach { valueParameter -> + if (valueParameter.isInlineParameter()) { expression.getValueArgument(valueParameter.index)?.let { if (isInlineIrExpression(it)) { (it as IrBlock).statements.filterIsInstance().forEach { reference -> @@ -97,10 +82,7 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa val argumentsCount = expression.valueArgumentsCount // Change calls to FunctionN with large N to varargs calls. val newCall = if (argumentsCount > MAX_ARGCOUNT_WITHOUT_VARARG && - descriptor.containingDeclaration in listOf( - context.builtIns.getFunction(argumentsCount), - context.reflectionTypes.getKFunction(argumentsCount) - ) + callee.parentAsClass.defaultType.isFunctionOrKFunction() ) { val vararg = IrVarargImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, @@ -108,14 +90,14 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa context.ir.symbols.any.typeWith(), (0 until argumentsCount).map { i -> expression.getValueArgument(i)!! } ) - val invokeFunDescriptor = context.getClass(FqName("kotlin.jvm.functions.FunctionN")) - .getFunction("invoke", listOf(expression.type.toKotlinType())) - val invokeFunSymbol = context.ir.symbols.externalSymbolTable.referenceSimpleFunction(invokeFunDescriptor.original) + val invokeFun = context.getIrClass(FqName("kotlin.jvm.functions.FunctionN")).owner.declarations.single { + it is IrSimpleFunction && it.name.asString() == "invoke" + } as IrSimpleFunction IrCallImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, expression.type, - invokeFunSymbol, invokeFunDescriptor, + invokeFun.symbol, invokeFun.descriptor, 1, expression.origin, expression.superQualifier?.let { context.ir.symbols.externalSymbolTable.referenceClass(it) } @@ -139,7 +121,8 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa return expression } - val loweredFunctionReference = FunctionReferenceBuilder(currentScope!!.scope.scopeOwner, expression).build() + val currentDeclarationParent = allScopes.map { it.irElement }.last { it is IrDeclarationParent } as IrDeclarationParent + val loweredFunctionReference = FunctionReferenceBuilder(currentDeclarationParent, expression).build() val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset) return irBuilder.irBlock(expression) { +loweredFunctionReference.functionReferenceClass @@ -158,26 +141,28 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa val functionReferenceConstructor: IrConstructor ) - private val kotlinPackageScope = context.builtIns.builtInsPackageScope - - private val continuationClassDescriptor = context.getClass(FqName("kotlin.coroutines.experimental.Continuation")) + private val continuationClass = context.getIrClass(FqName("kotlin.coroutines.experimental.Continuation")).owner //private val getContinuationSymbol = context.ir.symbols.getContinuation private inner class FunctionReferenceBuilder( - val containingDeclaration: DeclarationDescriptor, + val referenceParent: IrDeclarationParent, val irFunctionReference: IrFunctionReference ) { - private val functionDescriptor = irFunctionReference.descriptor - private val functionParameters = functionDescriptor.explicitParameters - private val boundFunctionParameters = irFunctionReference.getArguments().map { it.first } - private val unboundFunctionParameters = functionParameters - boundFunctionParameters + private val callee = irFunctionReference.symbol.owner + private val calleeParameters = callee.explicitParameters + private val boundCalleeParameters = irFunctionReference.getArgumentsWithIr().map { it.first } + private val unboundCalleeParameters = calleeParameters - boundCalleeParameters - private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl - private lateinit var functionReferenceClass: IrClassImpl + private val typeArgumentsMap = callee.typeParameters.associate { typeParam -> + typeParam to irFunctionReference.getTypeArgument(typeParam.index)!! + } + + + private lateinit var functionReferenceClass: IrClass private lateinit var functionReferenceThis: IrValueParameterSymbol - private lateinit var argumentToPropertiesMap: Map + private lateinit var argumentToFieldMap: Map private val isLambda = irFunctionReference.origin == IrStatementOrigin.LAMBDA @@ -189,600 +174,449 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa val startOffset = irFunctionReference.startOffset val endOffset = irFunctionReference.endOffset - val returnType = functionDescriptor.returnType!! - val superTypes: MutableList = mutableListOf( - functionReferenceOrLambda.descriptor.defaultType + val returnType = irFunctionReference.symbol.owner.returnType + val functionReferenceClassSuperTypes: MutableList = mutableListOf( + functionReferenceOrLambda.owner.defaultType // type arguments? ) - val numberOfParameters = unboundFunctionParameters.size + val numberOfParameters = unboundCalleeParameters.size useVararg = (numberOfParameters > MAX_ARGCOUNT_WITHOUT_VARARG) - val functionClassDescriptor = if (useVararg) - context.getClass(FqName("kotlin.jvm.functions.FunctionN")) + val functionClassSymbol = if (useVararg) + context.getIrClass(FqName("kotlin.jvm.functions.FunctionN")) else - context.getClass(FqName("kotlin.jvm.functions.Function$numberOfParameters")) - val functionParameterTypes = unboundFunctionParameters.map { it.type } + context.getIrClass(FqName("kotlin.jvm.functions.Function$numberOfParameters")) + val functionClass = functionClassSymbol.owner + val functionParameterTypes = unboundCalleeParameters.map { it.type } val functionClassTypeParameters = if (useVararg) listOf(returnType) else functionParameterTypes + returnType - superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters) + functionReferenceClassSuperTypes += IrSimpleTypeImpl( + functionClassSymbol, + hasQuestionMark = false, + arguments = functionClassTypeParameters.map { makeTypeProjection(it, Variance.INVARIANT) }, + annotations = emptyList() + ) - var suspendFunctionClassDescriptor: ClassDescriptor? = null - var suspendFunctionClassTypeParameters: List? = null - val lastParameterType = unboundFunctionParameters.lastOrNull()?.type - if (lastParameterType != null && TypeUtils.getClassDescriptor(lastParameterType) == continuationClassDescriptor) { + var suspendFunctionClass: IrClass? = null + var suspendFunctionClassTypeParameters: List? = null + val lastParameterType = unboundCalleeParameters.lastOrNull()?.type + if ((lastParameterType as? IrSimpleType)?.classifier == continuationClass) { // If the last parameter is Continuation<> inherit from SuspendFunction. - suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier( - Name.identifier("SuspendFunction${numberOfParameters - 1}"), NoLookupLocation.FROM_BACKEND - ) as ClassDescriptor - suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + lastParameterType.arguments.single().type - superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeParameters) + suspendFunctionClass = context.getIrClass(FqName("kotlin.Suspendfunction${numberOfParameters - 1}")).owner + suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + + (lastParameterType.arguments.single() as IrTypeProjection).type + functionReferenceClassSuperTypes += IrSimpleTypeImpl( + suspendFunctionClass.symbol, + hasQuestionMark = false, + arguments = suspendFunctionClassTypeParameters.map { makeTypeProjection(it, Variance.INVARIANT) }, + annotations = emptyList() + ) } - functionReferenceClassDescriptor = ClassDescriptorImpl( - /* containingDeclaration = */ containingDeclaration, - /* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName, - /* modality = */ Modality.FINAL, - /* kind = */ ClassKind.CLASS, - /* superTypes = */ superTypes, - /* source = */ /*TODO*/ (containingDeclaration as? DeclarationDescriptorWithSource)?.source ?: NO_SOURCE, - /* isExternal = */ false, - LockBasedStorageManager.NO_LOCKS - ) + val functionReferenceClassDescriptor = WrappedClassDescriptor() functionReferenceClass = IrClassImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, - descriptor = functionReferenceClassDescriptor + startOffset, endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrClassSymbolImpl(functionReferenceClassDescriptor), + name = "${callee.name}\$${functionReferenceCount++}".synthesizedName, + kind = ClassKind.CLASS, + visibility = Visibilities.PUBLIC, + modality = Modality.FINAL, + isCompanion = false, + isInner = false, + isData = false, + isExternal = false, + isInline = false ).apply { - createParameterDeclarations() - val typeTranslator = TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings, - enterTableScope=true) - val constantValueGenerator = ConstantValueGenerator(context.state.module, context.ir.symbols.externalSymbolTable) - typeTranslator.constantValueGenerator = constantValueGenerator - constantValueGenerator.typeTranslator = typeTranslator - functionReferenceClassDescriptor.typeConstructor.supertypes.mapTo(this.superTypes) { - typeTranslator.translateType(it) - } + functionReferenceClassDescriptor.bind(this) + parent = referenceParent + superTypes.addAll(functionReferenceClassSuperTypes) + createImplicitParameterDeclarationWithWrappedDescriptor() } - val contributedDescriptors = mutableListOf() - val constructorBuilder = createConstructorBuilder() - functionReferenceClassDescriptor.initialize( - SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null - ) - functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol - val invokeFunctionDescriptor = functionClassDescriptor.getFunction("invoke", functionClassTypeParameters) + argumentToFieldMap = boundCalleeParameters.associate { + it to buildField(it.name.safeName(), it.type) + } - val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionDescriptor) + val constructor = createConstructor() + functionReferenceClass.declarations.add(constructor) - constructorBuilder.initialize() - functionReferenceClass.declarations.add(constructorBuilder.ir) - - invokeMethodBuilder.initialize() - functionReferenceClass.declarations.add(invokeMethodBuilder.ir) + val superInvokeFunction = functionClass.functions.find { it.name.asString() == "invoke" }!! + val invokeMethod = createInvokeMethod(superInvokeFunction) + functionReferenceClass.declarations.add(invokeMethod) if (!isLambda) { - val getSignatureBuilder = - createGetSignatureMethodBuilder(functionReferenceOrLambda.owner.descriptor.getFunction("getSignature", emptyList())) - val getNameBuilder = createGetNameMethodBuilder(functionReferenceOrLambda.owner.descriptor.getProperty("name", emptyList())) - val getOwnerBuilder = - createGetOwnerMethodBuilder(functionReferenceOrLambda.owner.descriptor.getFunction("getOwner", emptyList())) + val getSignatureMethod = createGetSignatureMethod(functionReferenceOrLambda.owner.functions.find { it.name.asString() == "getSignature"}!!) + val getNameMethod = createGetNameMethod(functionReferenceOrLambda.owner.properties.find { it.name.asString() == "name" }!!) + val getOwnerMethod = createGetOwnerMethod(functionReferenceOrLambda.owner.functions.find { it.name.asString() == "getOwner" }!!) - val suspendInvokeMethodBuilder = - if (suspendFunctionClassDescriptor != null) { - val suspendInvokeFunctionDescriptor = - suspendFunctionClassDescriptor.getFunction("invoke", suspendFunctionClassTypeParameters!!) - createInvokeMethodBuilder(suspendInvokeFunctionDescriptor) + val suspendInvokeMethod = + if (suspendFunctionClass != null) { + val suspendInvokeFunction = + suspendFunctionClass.functions.find { it.name.asString() == "invoke" }!! + createInvokeMethod(suspendInvokeFunction) } else null - val inheritedScope = functionReferenceOrLambda.descriptor.unsubstitutedMemberScope - .getContributedDescriptors().mapNotNull { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) } - .filterNot { !isLambda && (it.name.asString() == "getSignature" || it.name.asString() == "name" || it.name.asString() == "getOwner") } - - contributedDescriptors.addAll( - ( - inheritedScope + invokeMethodBuilder.symbol.descriptor + - suspendInvokeMethodBuilder?.symbol?.descriptor + getSignatureBuilder.symbol.descriptor - ).filterNotNull() - ) - - getSignatureBuilder.initialize() - functionReferenceClass.declarations.add(getSignatureBuilder.ir) - - getNameBuilder.initialize() - functionReferenceClass.declarations.add(getNameBuilder.ir) - - getOwnerBuilder.initialize() - functionReferenceClass.declarations.add(getOwnerBuilder.ir) - - suspendInvokeMethodBuilder?.let { - it.initialize() - functionReferenceClass.declarations.add(it.ir) - } + functionReferenceClass.declarations.add(getSignatureMethod) + functionReferenceClass.declarations.add(getNameMethod) + functionReferenceClass.declarations.add(getOwnerMethod) + suspendInvokeMethod?.let { functionReferenceClass.declarations.add(it) } } - return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir) + return BuiltFunctionReference(functionReferenceClass, constructor) } - private fun createConstructorBuilder() = object : SymbolWithIrBuilder() { + private fun createConstructor(): IrConstructor { + val descriptor = WrappedClassConstructorDescriptor() + return IrConstructorImpl( + irFunctionReference.startOffset, irFunctionReference.endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrConstructorSymbolImpl(descriptor), + name = Name.special(""), + visibility = Visibilities.PUBLIC, + returnType = functionReferenceClass.defaultType, + isInline = false, + isExternal = false, + isPrimary = true + ).apply { + val constructor = this + descriptor.bind(this) + parent = functionReferenceClass - private val kFunctionRefConstructorSymbol = - functionReferenceOrLambda.constructors.filter { it.descriptor.valueParameters.size == if (isLambda) 1 else 2 }.single() - - override fun buildSymbol() = IrConstructorSymbolImpl( - ClassConstructorDescriptorImpl.create( - /* containingDeclaration = */ functionReferenceClassDescriptor, - /* annotations = */ Annotations.EMPTY, - /* isPrimary = */ false, - /* source = */ SourceElement.NO_SOURCE - ) - ) - - override fun doInitialize() { - val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl - val constructorParameters = boundFunctionParameters.mapIndexed { index, parameter -> - parameter.copyAsValueParameter(descriptor, index, parameter.name) - } - descriptor.initialize(constructorParameters, Visibilities.PUBLIC) - descriptor.returnType = functionReferenceClassDescriptor.defaultType - } - - override fun buildIr(): IrConstructor { - argumentToPropertiesMap = boundFunctionParameters.associate { - it to buildPropertyWithBackingField(it.name.safeName(), it.type) + val boundArgsSet = boundCalleeParameters.toSet() + for (param in callee.explicitParameters) { + if (param in boundArgsSet) { + val newParam = param.copyTo( + constructor, + index = valueParameters.size, + type = param.type.substitute(typeArgumentsMap) + ) + valueParameters.add(newParam) + } } - val startOffset = irFunctionReference.startOffset - val endOffset = irFunctionReference.endOffset - return IrConstructorImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, - symbol = symbol, - returnType = symbol.descriptor.returnType.toIrType()!! - ).apply { - val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset) + val kFunctionRefConstructorSymbol = + functionReferenceOrLambda.constructors.filter { it.owner.valueParameters.size == if (isLambda) 1 else 2 }.single() - createParameterDeclarations() + val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset) + body = irBuilder.irBlockBody { + +IrDelegatingConstructorCallImpl( + startOffset, endOffset, context.irBuiltIns.unitType, + kFunctionRefConstructorSymbol, kFunctionRefConstructorSymbol.descriptor + ).apply { + val const = + IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, unboundCalleeParameters.size) + putValueArgument(0, const) - body = irBuilder.irBlockBody { - +IrDelegatingConstructorCallImpl( - startOffset, endOffset, context.irBuiltIns.unitType, - kFunctionRefConstructorSymbol, kFunctionRefConstructorSymbol.descriptor - ).apply { - val const = - IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, unboundFunctionParameters.size) - putValueArgument(0, const) - - if (!isLambda) { - val irReceiver = valueParameters.firstOrNull() - val receiver = boundFunctionParameters.singleOrNull() - //TODO pass proper receiver - val receiverValue = receiver?.let { - irGet(irReceiver!!.symbol.owner) - } ?: irNull() - putValueArgument(1, receiverValue) - } + if (!isLambda) { + val irReceiver = valueParameters.firstOrNull() + val receiver = boundCalleeParameters.singleOrNull() + //TODO pass proper receiver + val receiverValue = receiver?.let { + irGet(irReceiver!!.symbol.owner) + } ?: irNull() + putValueArgument(1, receiverValue) } + } - //TODO don't write receiver again: use it from base class - boundFunctionParameters.forEachIndexed { index, it -> - +irSetField( - irGet(functionReferenceThis.owner), - argumentToPropertiesMap[it]!!.owner, - irGet(valueParameters[index]) + // Save all arguments to fields. + //TODO don't write receiver again: use it from base class + boundCalleeParameters.forEachIndexed { index, it -> + +irSetField( + irGet(functionReferenceThis.owner), + argumentToFieldMap[it]!!, + irGet(valueParameters[index]) + ) + } + +IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, context.irBuiltIns.unitType) + } + } + } + + private fun createInvokeMethod(superFunction: IrSimpleFunction) : IrSimpleFunction { + val descriptor = WrappedSimpleFunctionDescriptor() + return IrFunctionImpl( + irFunctionReference.startOffset, irFunctionReference.endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrSimpleFunctionSymbolImpl(descriptor), + Name.identifier("invoke"), + Visibilities.PUBLIC, + Modality.FINAL, + returnType = callee.returnType, + isInline = false, // not sure + isExternal = false, + isTailrec = false, + isSuspend = superFunction.isSuspend + ).apply { + val function = this + descriptor.bind(this) + parent = functionReferenceClass + overriddenSymbols.add(superFunction.symbol) + dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(function) + + val unboundArgsSet = unboundCalleeParameters.toSet() + if (useVararg) { + valueParameters.add(superFunction.valueParameters[0].copyTo(function)) + } else { + for (param in callee.explicitParameters) { + if (param in unboundArgsSet) { + val newParam = param.copyTo( + function, + index = valueParameters.size, + type = param.type.substitute(typeArgumentsMap) ) + valueParameters.add(newParam) } - +IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, context.irBuiltIns.unitType) - // Save all arguments to fields. - - } - } - } - } - - private fun createInvokeMethodBuilder(superFunctionDescriptor: FunctionDescriptor) = - object : SymbolWithIrBuilder() { - - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ functionReferenceClassDescriptor, - /* annotations = */ Annotations.EMPTY, - /* name = */ Name.identifier("invoke"), - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* source = */ SourceElement.NO_SOURCE - ) - ) - - override fun doInitialize() { - val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl - val valueParameters = superFunctionDescriptor.valueParameters - .map { it.copyAsValueParameter(descriptor, it.index) } - - descriptor.initialize( - /* receiverParameterType = */ null, - /* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter, - /* typeParameters = */ emptyList(), - /* unsubstitutedValueParameters = */ valueParameters, - /* unsubstitutedReturnType = */ superFunctionDescriptor.returnType, - /* modality = */ Modality.FINAL, - /* visibility = */ Visibilities.PUBLIC - ).apply { - overriddenDescriptors += superFunctionDescriptor - isSuspend = superFunctionDescriptor.isSuspend } } - override fun buildIr(): IrSimpleFunction { - val startOffset = irFunctionReference.startOffset - val endOffset = irFunctionReference.endOffset - val ourSymbol = symbol - return IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, - symbol = ourSymbol, - returnType = ourSymbol.descriptor.returnType!!.toIrType()!! - ).apply { - - val function = this - val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) - createParameterDeclarations() - - body = irBuilder.irBlockBody(startOffset, endOffset) { - val arrayGetFun = context.irBuiltIns.arrayClass.owner - .declarations.find { - (it as? IrSimpleFunction)?.name?.toString() == "get" - }!! as IrSimpleFunction - - if (useVararg) { - val varargParam = valueParameters.single() - val arraySizeProperty = context.irBuiltIns.arrayClass.owner.declarations.find { - (it as? IrProperty)?.name?.toString() == "size" - } as IrProperty - +irIfThen( - irNotEquals( - irCall(arraySizeProperty.getter!!).apply { - dispatchReceiver = irGet(varargParam) - }, - irInt(unboundFunctionParameters.size) - ), - irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply { - putValueArgument(0, irString("Expected ${unboundFunctionParameters.size} arguments")) - } - ) + val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) + body = irBuilder.irBlockBody(startOffset, endOffset) { + val arrayGetFun = context.irBuiltIns.arrayClass.owner.functions.find { it.name.asString() == "get" }!! + if (useVararg) { + val varargParam = valueParameters.single() + val arraySizeProperty = context.irBuiltIns.arrayClass.owner.properties.find { it.name.toString() == "size" }!! + +irIfThen( + irNotEquals( + irCall(arraySizeProperty.getter!!).apply { + dispatchReceiver = irGet(varargParam) + }, + irInt(unboundCalleeParameters.size) + ), + irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply { + putValueArgument(0, irString("Expected ${unboundCalleeParameters.size} arguments")) } - +irReturn( - irCall(irFunctionReference.symbol).apply { - var unboundIndex = 0 - val unboundArgsSet = unboundFunctionParameters.toSet() + ) + } + +irReturn( + irCall(irFunctionReference.symbol).apply { + var unboundIndex = 0 - functionParameters.forEach { parameter -> - val argument = when { - !unboundArgsSet.contains(parameter) -> - // Bound parameter - read from field. - irGetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[parameter]!!.owner) - ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size -> - // For suspend functions the last argument is continuation and it is implicit. - TODO() + calleeParameters.forEach { parameter -> + val argument = when { + !unboundArgsSet.contains(parameter) -> + // Bound parameter - read from field. + irGetField(irGet(functionReferenceThis.owner), argumentToFieldMap[parameter]!!) + function.isSuspend && unboundIndex == valueParameters.size -> + // For suspend functions the last argument is continuation and it is implicit. + TODO() // irCall(getContinuationSymbol, // listOf(ourSymbol.descriptor.returnType!!)) - useVararg -> { - val type = parameter.type.toIrType()!! - val varargParam = valueParameters.single() - irBlock(resultType = type) { - val argValue = irTemporary( - irCall(arrayGetFun).apply { - dispatchReceiver = irGet(varargParam) - putValueArgument(0, irInt(unboundIndex++)) - } - ) - +irIfThen( - irNotIs(irGet(argValue), type), - irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply { - putValueArgument(0, irString("Wrong type, expected $type")) - } - ) - +irGet(argValue) + useVararg -> { + val type = parameter.type + val varargParam = valueParameters.single() + irBlock(resultType = type) { + val argValue = irTemporary( + irCall(arrayGetFun).apply { + dispatchReceiver = irGet(varargParam) + putValueArgument(0, irInt(unboundIndex++)) } - } - else -> { - irGet(valueParameters[unboundIndex++]) - } - } - when (parameter) { - functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument - functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument - else -> putValueArgument((parameter as ValueParameterDescriptor).index, argument) + ) + +irIfThen( + irNotIs(irGet(argValue), type), + irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply { + putValueArgument(0, irString("Wrong type, expected $type")) + } + ) + +irGet(argValue) } } - - if (!useVararg) assert(unboundIndex == valueParameters.size) { "Not all arguments of are used" } + else -> { + irGet(valueParameters[unboundIndex++]) + } } - ) - } - } - } - } + when (parameter) { + callee.dispatchReceiverParameter -> dispatchReceiver = argument + callee.extensionReceiverParameter -> extensionReceiver = argument + else -> putValueArgument(parameter.index, argument) + } + } - private fun buildPropertyWithBackingField(name: Name, type: KotlinType): IrFieldSymbol { - val fieldSymbol = IrFieldSymbolImpl( - JvmPropertyDescriptorImpl.createFinalField( - name, type, functionReferenceClassDescriptor, - Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE - ) - ) + if (!useVararg) assert(unboundIndex == valueParameters.size) { "Not all arguments of are used" } + } + ) + } + + } + } + + private fun buildField(name: Name, type: IrType): IrField { + val descriptor = WrappedFieldDescriptor() + // TODO: make it synthetic val field = IrFieldImpl( irFunctionReference.startOffset, irFunctionReference.endOffset, DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, - fieldSymbol, - type.toIrType()!! - ) + IrFieldSymbolImpl(descriptor), + name, + type, + JavaVisibilities.PACKAGE_VISIBILITY, + isFinal = true, + isExternal = false, + isStatic = false + ).apply { + descriptor.bind(this) + } functionReferenceClass.declarations.add(field) - return fieldSymbol + return field } - private fun createGetNameMethodBuilder(superNameProperty: PropertyDescriptor) = - object : SymbolWithIrBuilder() { + private fun createGetSignatureMethod(superFunction: IrSimpleFunction): IrSimpleFunction { + val descriptor = WrappedSimpleFunctionDescriptor() + return IrFunctionImpl( + irFunctionReference.startOffset, irFunctionReference.endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrSimpleFunctionSymbolImpl(descriptor), + Name.identifier("getSignature"), + superFunction.visibility, + superFunction.modality, + returnType = superFunction.returnType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false + ).apply { + val function = this + descriptor.bind(this) + parent = functionReferenceClass + overriddenSymbols.add(superFunction.symbol) + dispatchReceiverParameter = functionReferenceClass.thisReceiver!!.copyTo(function) - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - PropertyDescriptorImpl.create( - /* containingDeclaration = */ functionReferenceClassDescriptor, - /* annotations = */ Annotations.EMPTY, - superNameProperty.modality, - superNameProperty.visibility, - false, - /* name = */ superNameProperty.name, - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* source = */ SourceElement.NO_SOURCE, - false, false, false, false, false, false - ).let { property -> - - property.overriddenDescriptors += superNameProperty - PropertyGetterDescriptorImpl( - property, - Annotations.EMPTY, - Modality.OPEN, - Visibilities.PUBLIC, - false, false, false, - CallableMemberDescriptor.Kind.DECLARATION, - null, - SourceElement.NO_SOURCE - ).also { - property.initialize(it, null) - property.setType( - /* outType = */ superNameProperty.type, - /* typeParameters = */ superNameProperty.typeParameters, - /* dispatchReceiverParameter = */ superNameProperty.dispatchReceiverParameter, - /* extensionReceiverParameter= */ superNameProperty.extensionReceiverParameter + val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) + body = irBuilder.irBlockBody(startOffset, endOffset) { + +irReturn( + IrConstImpl.string( + -1, -1, context.irBuiltIns.stringType, + PropertyReferenceCodegen.getSignatureString( + irFunctionReference.symbol.descriptor, this@CallableReferenceLowering.context.state ) - //overriddenDescriptors += superNameProperty.getter - } - } - ) - - override fun doInitialize() { - val descriptor = symbol.descriptor as PropertyGetterDescriptorImpl - descriptor.initialize(superNameProperty.type) - } - - override fun buildIr(): IrSimpleFunction { - val startOffset = irFunctionReference.startOffset - val endOffset = irFunctionReference.endOffset - val ourSymbol = symbol - return IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, - symbol = ourSymbol, - returnType = ourSymbol.descriptor.returnType!!.toIrType()!! - ).apply { - - val function = this - val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) - - createParameterDeclarations() - - body = irBuilder.irBlockBody(startOffset, endOffset) { - +irReturn( - IrConstImpl.string(-1, -1, context.irBuiltIns.stringType, functionDescriptor.name.asString()) - ) - } - } - } - } - - - private fun createGetSignatureMethodBuilder(superFunctionDescriptor: FunctionDescriptor) = - object : SymbolWithIrBuilder() { - - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ functionReferenceClassDescriptor, - /* annotations = */ Annotations.EMPTY, - /* name = */ Name.identifier("getSignature"), - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* source = */ SourceElement.NO_SOURCE - ) - ) - - override fun doInitialize() { - val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl - val valueParameters = superFunctionDescriptor.valueParameters - .map { it.copyAsValueParameter(descriptor, it.index) } - - descriptor.initialize( - /* receiverParameterType = */ null, - /* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter, - /* typeParameters = */ emptyList(), - /* unsubstitutedValueParameters = */ valueParameters, - /* unsubstitutedReturnType = */ superFunctionDescriptor.returnType, - /* modality = */ Modality.FINAL, - /* visibility = */ Visibilities.PUBLIC - ).apply { - overriddenDescriptors += superFunctionDescriptor - isSuspend = superFunctionDescriptor.isSuspend - } - } - - override fun buildIr(): IrSimpleFunction { - val startOffset = irFunctionReference.startOffset - val endOffset = irFunctionReference.endOffset - val ourSymbol = symbol - return IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, - symbol = ourSymbol, - returnType = ourSymbol.descriptor.returnType!!.toIrType()!! - ).apply { - - val function = this - val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) - - createParameterDeclarations() - - body = irBuilder.irBlockBody(startOffset, endOffset) { - +irReturn( - IrConstImpl.string( - -1, -1, context.irBuiltIns.stringType, - PropertyReferenceCodegen.getSignatureString( - irFunctionReference.symbol.descriptor, this@CallableReferenceLowering.context.state - ) - ) - ) - } - } - } - } - - private fun createGetOwnerMethodBuilder(superFunctionDescriptor: FunctionDescriptor) = - object : SymbolWithIrBuilder() { - - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ functionReferenceClassDescriptor, - /* annotations = */ Annotations.EMPTY, - /* name = */ Name.identifier("getOwner"), - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* source = */ SourceElement.NO_SOURCE - ) - ) - - override fun doInitialize() { - val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl - val valueParameters = superFunctionDescriptor.valueParameters - .map { it.copyAsValueParameter(descriptor, it.index) } - - descriptor.initialize( - /* receiverParameterType = */ null, - /* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter, - /* typeParameters = */ emptyList(), - /* unsubstitutedValueParameters = */ valueParameters, - /* unsubstitutedReturnType = */ superFunctionDescriptor.returnType, - /* modality = */ Modality.FINAL, - /* visibility = */ Visibilities.PUBLIC - ).apply { - overriddenDescriptors += superFunctionDescriptor - isSuspend = superFunctionDescriptor.isSuspend - } - } - - override fun buildIr(): IrSimpleFunction { - val startOffset = irFunctionReference.startOffset - val endOffset = irFunctionReference.endOffset - val ourSymbol = symbol - return IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, - symbol = ourSymbol, - returnType = symbol.descriptor.returnType!!.toIrType()!! - ).apply { - val function = this - val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) - - createParameterDeclarations() - - body = irBuilder.irBlockBody(startOffset, endOffset) { - +irReturn( - generateCallableReferenceDeclarationContainer(irFunctionReference) - ) - } - } - } - - fun IrBuilderWithScope.generateCallableReferenceDeclarationContainer( - irFunctionReference: IrFunctionReference - ): IrExpression { - val descriptor = irFunctionReference.symbol.descriptor - val globalContext = this@CallableReferenceLowering.context - val state = globalContext.state - val container = descriptor.containingDeclaration - - val type = - when { - container is ClassDescriptor -> - // TODO: getDefaultType() here is wrong and won't work for arrays - state.typeMapper.mapType(container.defaultType) - container is PackageFragmentDescriptor -> - state.typeMapper.mapOwner(descriptor) - descriptor is VariableDescriptorWithAccessors -> - globalContext.state.bindingContext.get( - CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, descriptor - )!! - else -> state.typeMapper.mapOwner(descriptor) - } - - val clazzDescriptor = globalContext.getClass(FqName("java.lang.Class")) - val clazzSymbol = globalContext.ir.symbols.externalSymbolTable.referenceClass(clazzDescriptor) - val clazzRef = IrClassReferenceImpl( - UNDEFINED_OFFSET, - UNDEFINED_OFFSET, - clazzDescriptor.toIrType(), - clazzSymbol, - CrIrType(type) - ) - - val isContainerPackage = if (descriptor is LocalVariableDescriptor) - DescriptorUtils.getParentOfType(descriptor, ClassDescriptor::class.java) == null - else - container is PackageFragmentDescriptor - - val reflectionClass = globalContext.getClass(FqName("kotlin.jvm.internal.Reflection")) - return if (isContainerPackage) { - // Note that this name is not used in reflection. There should be the name of the referenced declaration's module instead, - // but there's no nice API to obtain that name here yet - // TODO: write the referenced declaration's module name and use it in reflection - val module = IrConstImpl.string( - -1, -1, globalContext.irBuiltIns.stringType, - state.moduleName ) - val functionDescriptor = reflectionClass.getStaticFunction("getOrCreateKotlinPackage", emptyList()) - val functionSymbol = globalContext.ir.symbols.externalSymbolTable.referenceSimpleFunction(functionDescriptor) - irCall(functionSymbol, functionSymbol.owner.returnType).apply { - putValueArgument(0, clazzRef) - putValueArgument(1, module) - } - } else { - val functionDescriptor = reflectionClass.staticScope - .getContributedFunctions(Name.identifier("getOrCreateKotlinClass"), NoLookupLocation.FROM_BACKEND) - .single { it.valueParameters.size == 1 } - val functionSymbol = globalContext.ir.symbols.externalSymbolTable.referenceSimpleFunction(functionDescriptor) - irCall(functionSymbol, functionSymbol.owner.returnType).apply { - putValueArgument(0, clazzRef) - } - } + ) } } + } + private fun createGetNameMethod(superNameProperty: IrProperty): IrSimpleFunction { + val superGetter = superNameProperty.getter!! + val descriptor = WrappedSimpleFunctionDescriptor() + return IrFunctionImpl( + irFunctionReference.startOffset, irFunctionReference.endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrSimpleFunctionSymbolImpl(descriptor), + Name.identifier("getName"), + superGetter.visibility, + superGetter.modality, + returnType = superGetter.returnType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false + ).apply { + val function = this + descriptor.bind(this) + parent = functionReferenceClass + overriddenSymbols.add(superGetter.symbol) + dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(function) + val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) + body = irBuilder.irBlockBody(startOffset, endOffset) { + +irReturn( + IrConstImpl.string(-1, -1, context.irBuiltIns.stringType, callee.name.asString()) + ) + } + } + } + + private fun createGetOwnerMethod(superFunction: IrSimpleFunction): IrSimpleFunction { + val descriptor = WrappedSimpleFunctionDescriptor() + return IrFunctionImpl( + functionReferenceClass.startOffset, functionReferenceClass.endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrSimpleFunctionSymbolImpl(descriptor), + Name.identifier("getOwner"), + superFunction.visibility, + superFunction.modality, + returnType = superFunction.returnType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false + ).apply { + val function = this + descriptor.bind(this) + parent = functionReferenceClass + overriddenSymbols.add(superFunction.symbol) + dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(function) + + val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) + body = irBuilder.irBlockBody(startOffset, endOffset) { + +irReturn( + generateCallableReferenceDeclarationContainer() + ) + } + } + } + + fun IrBuilderWithScope.generateCallableReferenceDeclarationContainer(): IrExpression { + val globalContext = this@CallableReferenceLowering.context + val state = globalContext.state + val irContainer = callee.parent + + val isContainerPackage = + ((irContainer as? IrClass)?.origin == IrDeclarationOrigin.FILE_CLASS) || irContainer is IrPackageFragment + + val type = when { + irContainer is IrClass -> + // TODO: getDefaultType() here is wrong and won't work for arrays + state.typeMapper.mapType(irContainer.defaultType.toKotlinType()) + +// // TODO: this code is only needed for property references, which are not yet supported. +// descriptor is VariableDescriptorWithAccessors -> { +// assert(false) { "VariableDescriptorWithAccessors" } +// globalContext.state.bindingContext.get( +// CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, descriptor +// )!! +// } + + else -> state.typeMapper.mapOwner(callee.descriptor) + } + + val clazz = globalContext.getIrClass(FqName("java.lang.Class")).owner + val clazzRef = IrClassReferenceImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + clazz.defaultType, + clazz.symbol, + CrIrType(type) + ) + + val reflectionClass = globalContext.getIrClass(FqName("kotlin.jvm.internal.Reflection")) + return if (isContainerPackage) { + // Note that this name is not used in reflection. There should be the name of the referenced declaration's module instead, + // but there's no nice API to obtain that name here yet + // TODO: write the referenced declaration's module name and use it in reflection + val module = IrConstImpl.string( + -1, -1, globalContext.irBuiltIns.stringType, + state.moduleName + ) + val functionSymbol = reflectionClass.functions.find { it.owner.name.asString() == "getOrCreateKotlinPackage" }!! + irCall(functionSymbol, functionSymbol.owner.returnType).apply { + putValueArgument(0, clazzRef) + putValueArgument(1, module) + } + } else { + val functionSymbol = reflectionClass.functions.filter { it.owner.name.asString() == "getOrCreateKotlinClass" } + .single { it.owner.valueParameters.size == 1 } + irCall(functionSymbol, functionSymbol.owner.returnType).apply { + putValueArgument(0, clazzRef) + } + } + } } //TODO rewrite @@ -798,38 +632,41 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa } } -// Copied from K/Native IrUtils2.kt -// TODO move IrUtils2.kt to common -private fun IrClass.createParameterDeclarations() { - thisReceiver = IrValueParameterImpl( - startOffset, endOffset, - IrDeclarationOrigin.INSTANCE_RECEIVER, - descriptor.thisAsReceiverParameter, - this.symbol.typeWith(this.typeParameters.map { it.defaultType }), - null - ).also { valueParameter -> - valueParameter.parent = this +// TODO: Move to IrUtils + +private fun IrFunction.isInlineFunction(context: JvmBackendContext) = + (!context.state.isInlineDisabled || typeParameters.any { it.isReified }) && + (isInline || isArrayConstructorWithLambda()) + +private fun IrFunction.isArrayConstructorWithLambda() = + valueParameters.size == 2 && + this is IrConstructor && + parentAsClass.let { + it.getPackageFragment()?.fqName?.asString() == "kotlin" && + it.name.asString().endsWith("Array") + } + +private fun IrValueParameter.isInlineParameter() = + !isNoinline && !type.isNullable() && type.isFunctionOrKFunction() + +private fun IrType.substitute(substitutionMap: Map): IrType { + if (this !is IrSimpleType) return this + + substitutionMap[classifier]?.let { return it } + + val newArguments = arguments.map { + if (it is IrTypeProjection) { + makeTypeProjection(it.type.substitute(substitutionMap), it.variance) + } else { + it + } } - assert(typeParameters.isEmpty()) - assert(descriptor.declaredTypeParameters.isEmpty()) + val newAnnotations = annotations.map { it.deepCopyWithSymbols() } + return IrSimpleTypeImpl( + classifier, + hasQuestionMark, + newArguments, + newAnnotations + ) } - -private val IrTypeParameter.defaultType: IrType get() = this.symbol.defaultType - -private val IrTypeParameterSymbol.defaultType: IrType - get() = IrSimpleTypeImpl( - this, - false, - emptyList(), - emptyList() - ) - - -private fun IrClassifierSymbol.typeWith(arguments: List): IrSimpleType = - IrSimpleTypeImpl( - this, - false, - arguments.map { makeTypeProjection(it, Variance.INVARIANT) }, - emptyList() - ) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt index 4148967835d..3edd776c043 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt @@ -18,7 +18,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor -import org.jetbrains.kotlin.backend.common.makePhase +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality @@ -79,6 +79,7 @@ class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass { superTypes.add(context.irBuiltIns.anyType) parent = irFile declarations.addAll(fileClassMembers) + createImplicitParameterDeclarationWithWrappedDescriptor() // TODO: figure out why reparenting leads to failing tests. // fileClassMembers.forEach { it.parent = this } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt index bbf0c369005..a56bbb57bbf 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt @@ -29,6 +29,7 @@ interface IrDeclarationOrigin { object DELEGATED_MEMBER : IrDeclarationOriginImpl("DELEGATED_MEMBER") object ENUM_CLASS_SPECIAL_MEMBER : IrDeclarationOriginImpl("ENUM_CLASS_SPECIAL_MEMBER") object FUNCTION_FOR_DEFAULT_PARAMETER : IrDeclarationOriginImpl("FUNCTION_FOR_DEFAULT_PARAMETER") + object FILE_CLASS : IrDeclarationOriginImpl("FILE_CLASS") object GENERATED_DATA_CLASS_MEMBER : IrDeclarationOriginImpl("GENERATED_DATA_CLASS_MEMBER") object GENERATED_INLINE_CLASS_MEMBER : IrDeclarationOriginImpl("GENERATED_INLINE_CLASS_MEMBER") object LOCAL_FUNCTION_FOR_LAMBDA : IrDeclarationOriginImpl("LOCAL_FUNCTION_FOR_LAMBDA") @@ -48,4 +49,4 @@ interface IrDeclarationOrigin { abstract class IrDeclarationOriginImpl(val name: String) : IrDeclarationOrigin { override fun toString(): String = name -} \ No newline at end of file +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrField.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrField.kt index 8b55518304e..0fdfe1efc6d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrField.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrField.kt @@ -10,7 +10,8 @@ import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.types.IrType -interface IrField : IrSymbolDeclaration, IrOverridableDeclaration, IrDeclarationWithVisibility, IrDeclarationParent { +interface IrField : IrSymbolDeclaration, IrOverridableDeclaration, + IrDeclarationWithName, IrDeclarationWithVisibility, IrDeclarationParent { override val descriptor: PropertyDescriptor val type: IrType diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index 7c92b710080..54b4fa15ca1 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -33,8 +33,11 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import java.util.* -inline fun T.deepCopyWithSymbols(initialParent: IrDeclarationParent? = null): T { - val symbolRemapper = DeepCopySymbolRemapper() +inline fun T.deepCopyWithSymbols( + initialParent: IrDeclarationParent? = null, + descriptorRemapper: DescriptorsRemapper = DescriptorsRemapper.DEFAULT +): T { + val symbolRemapper = DeepCopySymbolRemapper(descriptorRemapper) acceptVoid(symbolRemapper) val typeRemapper = DeepCopyTypeRemapper(symbolRemapper) return transform(DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper), null).patchDeclarationParents(initialParent) as T diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index de8e1a2302b..34f86f11232 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -259,6 +259,9 @@ val IrClassSymbol.constructors: Sequence val IrClass.constructors: Sequence get() = this.declarations.asSequence().filterIsInstance() +val IrDeclarationContainer.properties: Sequence + get() = declarations.asSequence().filterIsInstance() + val IrFunction.explicitParameters: List get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters)