[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:
Pavel Kunyavskiy
2022-08-02 16:00:47 +02:00
committed by Space
parent 2f75ea585e
commit 5034581788
19 changed files with 235 additions and 42 deletions
@@ -13,9 +13,7 @@ import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunc
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering
import org.jetbrains.kotlin.backend.common.lower.loops.ForLoopsLowering
import org.jetbrains.kotlin.backend.common.lower.optimizations.FoldConstantLowering
import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.backend.common.ir.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
@@ -1,107 +0,0 @@
/*
* Copyright 2010-2021 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.
*/
/*
* Copyright 2010-2021 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.ir.backend.js.lower.inline
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.isInlineFunWithReifiedParameter
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
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.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.IrTypeSubstitutor
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.addFunction(container.parent as IrDeclarationContainer) {
name = Name.identifier("${owner.name}${"$"}wrap")
returnType = owner.returnType
visibility = DescriptorVisibilities.PRIVATE
origin = JsIrBuilder.SYNTHESIZED_DECLARATION
}.also { function ->
owner.valueParameters.forEach { valueParameter ->
function.addValueParameter(
valueParameter.name,
typeSubstitutor.substitute(valueParameter.type)
)
}
function.body = irFactory.createBlockBody(
expression.startOffset,
expression.endOffset
) {
statements.add(
JsIrBuilder.buildReturn(
function.symbol,
JsIrBuilder.buildCall(owner.symbol).also { call ->
call.dispatchReceiver = expression.dispatchReceiver
call.extensionReceiver = expression.extensionReceiver
function.valueParameters.forEachIndexed { index, valueParameter ->
call.putValueArgument(index, JsIrBuilder.buildGetValue(valueParameter.symbol))
}
for (i in 0 until expression.typeArgumentsCount) {
call.putTypeArgument(i, expression.getTypeArgument(i))
}
},
owner.returnType
)
)
}
}
return IrFunctionReferenceImpl.fromSymbolOwner(
expression.startOffset,
expression.endOffset,
expression.type,
function.symbol,
function.typeParameters.size,
expression.reflectionTarget
)
}
})
}
}
@@ -118,5 +118,3 @@ fun invokeFunForLambda(call: IrCall) =
.type
.getClass()!!
.invokeFun!!
fun IrFunction.isInlineFunWithReifiedParameter() = isInline && typeParameters.any { it.isReified }