[JS IR] Use a copy of an original inline function for inlining

If inline function A calls another inline function B,
 we must use the original version of inline function A for inlining,
 which doesn’t have inlined function B. Because during the inlining
 process, we remap all occurrences of inline function A
 to a temporary copy of function A, and if the function B
 somehow uses function A (e.g. callable reference),
 the built IR will have a reference to the temporary function,
 not the original one. All these things lead to broken cross-module references.

 This patch saves the original versions of all inline functions
 before inlining and provides them during the inline process.

^KT-55930 Fixed
This commit is contained in:
Alexander Korepanov
2023-01-13 16:07:00 +01:00
committed by Space Team
parent 82d934d873
commit a5c8e30bb1
9 changed files with 110 additions and 7 deletions
@@ -42,6 +42,7 @@ fun IrExpression.isAdaptedFunctionReference() =
interface InlineFunctionResolver {
fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction
fun getFunctionSymbol(irFunction: IrFunction): IrFunctionSymbol
}
fun IrFunction.isTopLevelInPackage(name: String, packageName: String): Boolean {
@@ -72,6 +73,10 @@ open class DefaultInlineFunctionResolver(open val context: CommonBackendContext)
else -> (symbol.owner as? IrSimpleFunction)?.resolveFakeOverride() ?: symbol.owner
}
}
override fun getFunctionSymbol(irFunction: IrFunction): IrFunctionSymbol {
return irFunction.symbol
}
}
class FunctionInlining(
@@ -206,7 +211,7 @@ class FunctionInlining(
symbol = irReturnableBlockSymbol,
origin = null,
statements = newStatements,
inlineFunctionSymbol = callee.symbol
inlineFunctionSymbol = inlineFunctionResolver.getFunctionSymbol(callee)
).apply {
transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitReturn(expression: IrReturn): IrExpression {