[K/N] Fix references for inline function
Corresponding lowering creating wrappers from JS Backend was used. Also, the lowering was changed to create local function, instead of normal one in outer scope, as a lot of logic from local declarations lowering should be duplicated otherwise for correct type parameters handling. ^KT-38535
This commit is contained in:
@@ -119,3 +119,5 @@ fun CommonBackendContext.createArrayOfExpression(
|
||||
putValueArgument(0, arg0)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunction.isInlineFunWithReifiedParameter() = isInline && typeParameters.any { it.isReified }
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.ir.isInlineFunWithReifiedParameter
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeArgument
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeSubstitutor
|
||||
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
|
||||
import org.jetbrains.kotlin.ir.util.typeSubstitutionMap
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
// Replace callable reference on inline function with reified parameter
|
||||
// with callable reference on new non inline function with substituted types
|
||||
class WrapInlineDeclarationsWithReifiedTypeParametersLowering(val context: BackendContext) : BodyLoweringPass {
|
||||
private val irFactory
|
||||
get() = context.irFactory
|
||||
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.transformChildrenVoid()
|
||||
|
||||
val owner = expression.symbol.owner as? IrSimpleFunction
|
||||
?: return expression
|
||||
|
||||
if (!owner.isInlineFunWithReifiedParameter()) {
|
||||
return expression
|
||||
}
|
||||
val substitutionMap = expression.typeSubstitutionMap
|
||||
.entries
|
||||
.map { (key, value) ->
|
||||
key to (value as IrTypeArgument)
|
||||
}
|
||||
val typeSubstitutor = IrTypeSubstitutor(
|
||||
substitutionMap.map { it.first },
|
||||
substitutionMap.map { it.second },
|
||||
context.irBuiltIns
|
||||
)
|
||||
|
||||
val function = irFactory.buildFun {
|
||||
name = Name.identifier("${owner.name}${"$"}wrap")
|
||||
returnType = typeSubstitutor.substitute(owner.returnType)
|
||||
visibility = DescriptorVisibilities.LOCAL
|
||||
origin = IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE
|
||||
startOffset = SYNTHETIC_OFFSET
|
||||
endOffset = SYNTHETIC_OFFSET
|
||||
}.apply {
|
||||
parent = container as IrDeclarationParent
|
||||
val irBuilder = context.createIrBuilder(symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET)
|
||||
owner.valueParameters.forEach { valueParameter ->
|
||||
addValueParameter(
|
||||
valueParameter.name,
|
||||
typeSubstitutor.substitute(valueParameter.type)
|
||||
)
|
||||
}
|
||||
body = irFactory.createBlockBody(
|
||||
expression.startOffset,
|
||||
expression.endOffset
|
||||
) {
|
||||
statements.add(
|
||||
irBuilder.irReturn(
|
||||
irBuilder.irCall(owner.symbol).also { call ->
|
||||
call.dispatchReceiver = expression.dispatchReceiver
|
||||
call.extensionReceiver = expression.extensionReceiver
|
||||
valueParameters.forEachIndexed { index, valueParameter ->
|
||||
call.putValueArgument(index, irBuilder.irGet(valueParameter))
|
||||
}
|
||||
for (i in 0 until expression.typeArgumentsCount) {
|
||||
call.putTypeArgument(i, expression.getTypeArgument(i))
|
||||
}
|
||||
},
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return context.createIrBuilder(container.symbol).irBlock(
|
||||
expression,
|
||||
origin = IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE
|
||||
) {
|
||||
+function
|
||||
+IrFunctionReferenceImpl.fromSymbolOwner(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
expression.type,
|
||||
function.symbol,
|
||||
function.typeParameters.size,
|
||||
expression.reflectionTarget
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user