From 2381e453d8bd8b348ccb4f47d1d2c875a842655c Mon Sep 17 00:00:00 2001 From: Konstantin Anisimov Date: Mon, 3 Apr 2017 09:43:33 +0700 Subject: [PATCH] Type substitution relocated in DeepCopyIrWithDescriptors --- .../common/DeepCopyIrTreeWithDescriptoros.kt | 291 +++++++++++++----- .../backend/konan/lower/FunctionInlining.kt | 51 +-- 2 files changed, 217 insertions(+), 125 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt index 294b5067a17..423f0a70010 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.common import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl @@ -28,9 +29,12 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -38,8 +42,12 @@ 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.name.Name +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.Variance -internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val context: Context) { +internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val typeSubstitutor: TypeSubstitutor?, val context: Context) { private val descriptorSubstituteMap: MutableMap = mutableMapOf() private var inlinedFunctionName = "" @@ -48,6 +56,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val //-------------------------------------------------------------------------// fun copy(irElement: IrElement, functionName: String) { + inlinedFunctionName = functionName descriptorSubstituteMap.clear() irElement.acceptChildrenVoid(descriptorCollector) @@ -58,30 +67,16 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val private val descriptorCollector = object : IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildren(this, null) - } - - //---------------------------------------------------------------------// - - override fun visitFunction(declaration: IrFunction) { - val oldDescriptor = declaration.descriptor - val newDescriptor = copyFunctionDescriptor(oldDescriptor) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - super.visitFunction(declaration) - } - - //---------------------------------------------------------------------// - override fun visitClass(declaration: IrClass) { + val oldDescriptor = declaration.descriptor val newDescriptor = copyClassDescriptor(oldDescriptor) descriptorSubstituteMap[oldDescriptor] = newDescriptor descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter super.visitClass(declaration) - val constructors = oldDescriptor.constructors.map { - descriptorSubstituteMap[it] as ClassConstructorDescriptor + val constructors = oldDescriptor.constructors.map { oldConstructorDescriptor -> + descriptorSubstituteMap[oldConstructorDescriptor] as ClassConstructorDescriptor }.toSet() var primaryConstructor: ClassConstructorDescriptor? = null @@ -104,9 +99,60 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val ) } + //---------------------------------------------------------------------// + + override fun visitFunction(declaration: IrFunction) { + + val oldDescriptor = declaration.descriptor + val newDescriptor = copyFunctionDescriptor(oldDescriptor) + descriptorSubstituteMap[oldDescriptor] = newDescriptor + super.visitFunction(declaration) + } + + //---------------------------------------------------------------------// + + override fun visitCall(expression: IrCall) { + + val descriptor = expression.descriptor as FunctionDescriptor + if (descriptor.isFunctionInvoke) { + val oldDescriptor = descriptor as SimpleFunctionDescriptor + val containingDeclaration = targetFunction.descriptor + val newReturnType = substituteType(oldDescriptor.returnType)!! + val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, containingDeclaration) + val newDescriptor = oldDescriptor.newCopyBuilder().apply { + setReturnType(newReturnType) + setValueParameters(newValueParameters) + }.build() + descriptorSubstituteMap[oldDescriptor] = newDescriptor!! + } + + super.visitCall(expression) + } + + //---------------------------------------------------------------------// + + override fun visitVariable(declaration: IrVariable) { + + val oldDescriptor = declaration.descriptor + val newDescriptor = IrTemporaryVariableDescriptorImpl( + targetFunction.descriptor, + generateName(oldDescriptor.name), + substituteType(oldDescriptor.type)!!, + oldDescriptor.isVar) + descriptorSubstituteMap[oldDescriptor] = newDescriptor + super.visitVariable(declaration) + } + + //---------------------------------------------------------------------// + + override fun visitElement(element: IrElement) { + element.acceptChildren(this, null) + } + //--- Copy descriptors ------------------------------------------------// private fun generateName(name: Name): Name { + val containingName = targetFunction.descriptor.name.toString() // Name of inline target (function we inline in) val declarationName = name.toString() // Name of declaration val indexStr = (nameIndex++).toString() // Unique for inline target index @@ -115,33 +161,11 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val //---------------------------------------------------------------------// - private fun copyValueParameters(oldValueParameters: List , owner: CallableDescriptor): List { - return oldValueParameters.map { oldDescriptor -> - val newDescriptor = ValueParameterDescriptorImpl( - owner, - oldDescriptor.original, - oldDescriptor.index, - oldDescriptor.annotations, - oldDescriptor.name, - oldDescriptor.type, - oldDescriptor.declaresDefaultValue(), - oldDescriptor.isCrossinline, - oldDescriptor.isNoinline, - oldDescriptor.varargElementType, - oldDescriptor.source - ) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - newDescriptor - } - } - - //---------------------------------------------------------------------// - - private fun copyFunctionDescriptor(oldDescriptor: FunctionDescriptor): FunctionDescriptor { + private fun copyFunctionDescriptor(oldDescriptor: CallableDescriptor): CallableDescriptor { return when (oldDescriptor) { - is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor) - is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor) + is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor) + is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor) else -> TODO("Unsupported FunctionDescriptor subtype") } } @@ -150,30 +174,29 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor) : FunctionDescriptor { - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val memberOwner = descriptorSubstituteMap[oldContainingDeclaration] ?: targetFunction.descriptor + val containingDeclaration = targetFunction.descriptor val newDescriptor = SimpleFunctionDescriptorImpl.create( - memberOwner, + containingDeclaration, oldDescriptor.annotations, generateName(oldDescriptor.name), CallableMemberDescriptor.Kind.SYNTHESIZED, oldDescriptor.source ).apply { isTailrec = oldDescriptor.isTailrec } - val oldDispatchReceiverParameter = oldDescriptor.dispatchReceiverParameter - val newDispatchReceiverParameter = - if (oldDispatchReceiverParameter == null) null - else descriptorSubstituteMap[oldDispatchReceiverParameter] - val newTypeParameters = oldDescriptor.typeParameters - val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, newDescriptor) + val newDispatchReceiverParameter = null // TODO + val newTypeParameters = oldDescriptor.typeParameters + val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, containingDeclaration) + val receiverParameterType = substituteType(oldDescriptor.extensionReceiverParameter?.type) + val returnType = substituteType(oldDescriptor.returnType) + assert(newTypeParameters.isEmpty()) newDescriptor.initialize( - oldDescriptor.extensionReceiverParameter?.type, - newDispatchReceiverParameter as? ReceiverParameterDescriptor, + receiverParameterType, + newDispatchReceiverParameter, newTypeParameters, newValueParameters, - oldDescriptor.returnType, - Modality.FINAL, + returnType, + oldDescriptor.modality, oldDescriptor.visibility ) newDescriptor.overriddenDescriptors += oldDescriptor.overriddenDescriptors @@ -193,14 +216,18 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val oldDescriptor.source ) - val newTypeParameters = oldDescriptor.typeParameters - val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, newDescriptor) + val newTypeParameters = oldDescriptor.typeParameters + val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, newDescriptor) + val receiverParameterType = substituteType(oldDescriptor.dispatchReceiverParameter?.type) + val returnType = substituteType(oldDescriptor.returnType) + assert(newTypeParameters.isEmpty()) + newDescriptor.initialize( - oldDescriptor.dispatchReceiverParameter?.type, + receiverParameterType, null, // TODO @Nullable ReceiverParameterDescriptor dispatchReceiverParameter, newTypeParameters, newValueParameters, - oldDescriptor.returnType, + returnType, oldDescriptor.modality, oldDescriptor.visibility ) @@ -252,6 +279,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val //---------------------------------------------------------------------// override fun visitFunction(declaration: IrFunction): IrStatement { + val oldDeclaration = super.visitFunction(declaration) as IrFunction val newDescriptor = descriptorSubstituteMap[oldDeclaration.descriptor] if (newDescriptor == null) return oldDeclaration @@ -267,29 +295,37 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val override fun visitCall(expression: IrCall): IrExpression { - val irCall = super.visitCall(expression) as IrCall - if (irCall !is IrCallImpl) return irCall // TODO what other kinds of call can we meet? + val oldExpression = super.visitCall(expression) as IrCall + if (oldExpression !is IrCallImpl) return oldExpression // TODO what other kinds of call can we meet? - val oldDescriptor = irCall.descriptor - val newDescriptor = descriptorSubstituteMap.getOrDefault(oldDescriptor.original, - oldDescriptor) as FunctionDescriptor + val oldDescriptor = oldExpression.descriptor + val newDescriptor = descriptorSubstituteMap.getOrDefault(oldDescriptor, oldDescriptor) - val oldSuperQualifier = irCall.superQualifier + val oldSuperQualifier = oldExpression.superQualifier var newSuperQualifier: ClassDescriptor? = oldSuperQualifier if (newSuperQualifier != null) { newSuperQualifier = descriptorSubstituteMap.getOrDefault(newSuperQualifier, newSuperQualifier) as ClassDescriptor } - return IrCallImpl(irCall.startOffset, irCall.endOffset, irCall.type, newDescriptor, - irCall.typeArguments, irCall.origin, newSuperQualifier).apply { - irCall.descriptor.valueParameters.forEach { - val valueArgument = irCall.getValueArgument(it) + val newExpression = IrCallImpl( + oldExpression.startOffset, + oldExpression.endOffset, + substituteType(oldExpression.type)!!, + newDescriptor as FunctionDescriptor, + substituteTypeArguments(oldExpression.typeArguments), + oldExpression.origin, + newSuperQualifier + ).apply { + oldExpression.descriptor.valueParameters.forEach { + val valueArgument = oldExpression.getValueArgument(it) putValueArgument(it.index, valueArgument) } - extensionReceiver = irCall.extensionReceiver - dispatchReceiver = irCall.dispatchReceiver + extensionReceiver = oldExpression.extensionReceiver + dispatchReceiver = oldExpression.dispatchReceiver } + + return newExpression } //---------------------------------------------------------------------// @@ -301,11 +337,16 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val val newDescriptor = descriptorSubstituteMap[oldDescriptor] if (newDescriptor == null) return oldReference - val typeArguments = (oldReference as IrMemberAccessExpressionBase).typeArguments - val newReference = IrCallableReferenceImpl(expression.startOffset, - oldReference.endOffset, oldReference.type, newDescriptor as CallableDescriptor, - typeArguments, oldReference.origin) - + val oldTypeArguments = (oldReference as IrMemberAccessExpressionBase).typeArguments + val newTypeArguments = substituteTypeArguments(oldTypeArguments) + val newReference = IrCallableReferenceImpl( + expression.startOffset, + oldReference.endOffset, + substituteType(oldReference.type)!!, + newDescriptor as CallableDescriptor, + newTypeArguments, + oldReference.origin + ) return newReference } @@ -318,9 +359,13 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val val newDescriptor = descriptorSubstituteMap[oldDescriptor] if (newDescriptor == null) return oldReturn - val newReturn = IrReturnImpl(oldReturn.startOffset, oldReturn.endOffset, - oldReturn.type, newDescriptor as CallableDescriptor, oldReturn.value) - + val newReturn = IrReturnImpl( + oldReturn.startOffset, + oldReturn.endOffset, + substituteType(oldReturn.type)!!, + newDescriptor as CallableDescriptor, + oldReturn.value + ) return newReturn } @@ -334,12 +379,48 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val if (newDescriptor == null) return oldExpression val newExpression = IrGetValueImpl( - oldExpression.startOffset, oldExpression.endOffset, - newDescriptor as ValueParameterDescriptor, oldExpression.origin + oldExpression.startOffset, + oldExpression.endOffset, + newDescriptor as ValueDescriptor, + oldExpression.origin ) return newExpression } + //---------------------------------------------------------------------// + + override fun visitSetVariable(expression: IrSetVariable): IrExpression { + + val oldExpression = super.visitSetVariable(expression) as IrSetVariable + val oldDescriptor = oldExpression.descriptor + val newDescriptor = descriptorSubstituteMap[oldDescriptor] + if (newDescriptor == null) return oldExpression + + val newExpression = IrSetVariableImpl( + oldExpression.startOffset, + oldExpression.endOffset, + newDescriptor as VariableDescriptor, + oldExpression.value, + oldExpression.origin + ) + return newExpression + } + + //---------------------------------------------------------------------// + + override fun visitVariable(declaration: IrVariable): IrStatement { + val oldDeclaration = super.visitVariable(declaration) as IrVariable + val newDescriptor = descriptorSubstituteMap[oldDeclaration.descriptor] + val newDeclaration = IrVariableImpl( + oldDeclaration.startOffset, + oldDeclaration.endOffset, + oldDeclaration.origin, + newDescriptor as VariableDescriptor, + oldDeclaration.initializer + ) + return newDeclaration + } + //--- Copy declarations -----------------------------------------------// private fun copyIrFunctionImpl(oldDeclaration: IrFunction, newDescriptor: DeclarationDescriptor): IrFunction { @@ -358,4 +439,50 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val ) } } + + //-------------------------------------------------------------------------// + + private fun substituteType(oldType: KotlinType?): KotlinType? { + if (typeSubstitutor == null) return oldType + if (oldType == null) return oldType + return typeSubstitutor.substitute(oldType, Variance.INVARIANT) ?: oldType + } + + //---------------------------------------------------------------------// + + private fun substituteTypeArguments(oldTypeArguments: Map ?): Map ? { + + if (oldTypeArguments == null) return null + if (typeSubstitutor == null) return oldTypeArguments + + val newTypeArguments = oldTypeArguments.entries.associate { + val typeParameterDescriptor = it.key + val oldTypeArgument = it.value + val newTypeArgument = substituteType(oldTypeArgument)!! + typeParameterDescriptor to newTypeArgument + } + return newTypeArguments + } + //---------------------------------------------------------------------// + + private fun copyValueParameters(oldValueParameters: List , containingDeclaration: CallableDescriptor): List { + + return oldValueParameters.map { oldDescriptor -> + val newDescriptor = ValueParameterDescriptorImpl( + containingDeclaration, + oldDescriptor.original, + oldDescriptor.index, + oldDescriptor.annotations, + oldDescriptor.name, + substituteType(oldDescriptor.type)!!, + oldDescriptor.declaresDefaultValue(), + oldDescriptor.isCrossinline, + oldDescriptor.isNoinline, + substituteType(oldDescriptor.varargElementType), + oldDescriptor.source + ) + descriptorSubstituteMap[oldDescriptor] = newDescriptor + newDescriptor + } + } } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt index dc478b788ad..4be8f7ef4a6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt @@ -77,7 +77,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( override fun visitFunction(declaration: IrFunction): IrStatement { currentFunction = declaration currentScope = Scope(declaration.descriptor) - copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, context) return super.visitFunction(declaration) } @@ -192,8 +191,11 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val originBlockBody = functionDeclaration.body if (originBlockBody == null) return null // TODO workaround - val copyBlockBody = originBlockBody.accept(InlineCopyIr(), null) as IrBlockBody // Create copy of original function body. + val typeSubstitutor = createTypeSubstitutor(typeArgsMap) + copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeSubstitutor, context) val functionName = functionDeclaration.descriptor.name.toString() + + val copyBlockBody = originBlockBody.accept(InlineCopyIr(), null) as IrBlockBody // Create copy of original function body. copyWithDescriptors!!.copy(copyBlockBody, functionName) // TODO merge DeepCopyIrTreeWithDescriptors with InlineCopyIr val originalDescriptor = functionDeclaration.descriptor.original @@ -212,7 +214,8 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( if (irDeclaration == null) return irCall val functionDeclaration = irDeclaration as IrFunction - val inlineBody = createInlineFunctionBody(functionDeclaration) + val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments + val inlineBody = createInlineFunctionBody(functionDeclaration, typeArgsMap) if (inlineBody == null) return irCall val parametersOld = getArguments(irCall, functionDeclaration) // Create map call_site_argument -> inline_function_parameter. @@ -222,7 +225,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val lambdaInliner = LambdaInliner(parameterToArgument) inlineBody.transformChildrenVoid(lambdaInliner) - val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments val transformer = ParametersTransformer(parameterToArgument, typeArgsMap, evaluationStatements) inlineBody.transformChildrenVoid(transformer) // Replace parameters with expression. inlineBody.statements.addAll(0, evaluationStatements) @@ -283,6 +285,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( //---------------------------------------------------------------------// override fun visitGetValue(expression: IrGetValue): IrExpression { + val newExpression = super.visitGetValue(expression) as IrGetValue val descriptor = newExpression.descriptor val argument = substituteMap[descriptor]?.accept(InlineCopyIr(), null) as IrExpression? // Find expression to replace this parameter. @@ -293,44 +296,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( //---------------------------------------------------------------------// - private fun newVariable(oldVariable: IrVariable): IrVariable { - val initializer = oldVariable.initializer!! - val isMutable = oldVariable.descriptor.isVar - val varName = currentScope!!.scopeOwner.name.toString() + "_inline" - return currentScope!!.createTemporaryVariable(initializer, varName, isMutable) // Create new variable and init it with the parameter expression. - } - - //---------------------------------------------------------------------// - - override fun visitVariable(declaration: IrVariable): IrStatement { - - val newDeclaration = super.visitVariable(declaration) as IrVariable // Process variable initializer. - val newVariable = newVariable(newDeclaration) // Create new local variable. - val getVal = IrGetValueImpl(0, 0, newVariable.descriptor) // Create new IR element representing access the new variable. - val descriptor = declaration.descriptor.original as ValueDescriptor - substituteMap[descriptor] = getVal - return newVariable - } - - //---------------------------------------------------------------------// - - override fun visitSetVariable(expression: IrSetVariable): IrExpression { - - val result = super.visitSetVariable(expression) - val substitute = substituteMap[expression.descriptor] // Get substitution for this variable. - if (substitute == null) return result // If there is no substitution - do nothing. - - val startOffset = expression.startOffset - val endOffset = expression.endOffset - val descriptor = (substitute as IrGetValue).descriptor as VariableDescriptor - val value = expression.value - val origin = expression.origin - - return IrSetVariableImpl(startOffset, endOffset, descriptor, value, origin) // Create SetVariable expression for the new descriptor. - } - - //---------------------------------------------------------------------// - private fun createTypeSubstitutor(): TypeSubstitutor { val substitutionContext = typeArgsMap!!.entries.associate { @@ -467,7 +432,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val copyLambdaFunction = lambdaFunction.accept(InlineCopyIr(), // Create copy of the function. null) as IrFunction - copyWithDescriptors!!.copy(copyLambdaFunction, "lambda") // TODO merge DeepCopyIrTreeWithDescriptors with InlineCopyIr + copyWithDescriptors!!.copy(copyLambdaFunction, "lambda") // TODO merge DeepCopyIrTreeWithDescriptors with InlineCopyIr val lambdaStatements = (copyLambdaFunction.body as IrBlockBody).statements val lambdaReturnType = copyLambdaFunction.descriptor.returnType!!