[IR] Inliner: supported tricky function references
This includes references to functions with varargs and default arguments
This commit is contained in:
+43
-13
@@ -24,8 +24,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNullable
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
@@ -201,34 +200,65 @@ class FunctionInlining(val context: CommonBackendContext) : IrElementTransformer
|
||||
val unboundArgsSet = unboundFunctionParameters.toSet()
|
||||
val valueParameters = expression.getArgumentsWithIr().drop(1) // Skip dispatch receiver.
|
||||
|
||||
val superType = functionArgument.type as IrSimpleType
|
||||
val superTypeArgumentsMap = expression.symbol.owner.parentAsClass.typeParameters.associate { typeParam ->
|
||||
typeParam.symbol to superType.arguments[typeParam.index].typeOrNull!!
|
||||
}
|
||||
|
||||
val immediateCall = with(expression) {
|
||||
if (function is IrConstructor) {
|
||||
val classTypeParametersCount = function.parentAsClass.typeParameters.size
|
||||
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, function.returnType, function.symbol, classTypeParametersCount)
|
||||
IrConstructorCallImpl.fromSymbolOwner(
|
||||
startOffset,
|
||||
endOffset,
|
||||
function.returnType,
|
||||
function.symbol,
|
||||
classTypeParametersCount
|
||||
)
|
||||
} else
|
||||
IrCallImpl(startOffset, endOffset, function.returnType, functionArgument.symbol)
|
||||
}.apply {
|
||||
functionParameters.forEach {
|
||||
for (parameter in functionParameters) {
|
||||
val argument =
|
||||
if (unboundArgsSet.contains(it)) {
|
||||
assert(unboundIndex < valueParameters.size) {
|
||||
"Attempt to use unbound parameter outside of the callee's value parameters"
|
||||
}
|
||||
valueParameters[unboundIndex++].second
|
||||
} else {
|
||||
val arg = boundFunctionParametersMap[it]!!
|
||||
if (parameter !in unboundArgsSet) {
|
||||
val arg = boundFunctionParametersMap[parameter]!!
|
||||
if (arg is IrGetValueWithoutLocation)
|
||||
arg.withLocation(expression.startOffset, expression.endOffset)
|
||||
else arg
|
||||
} else {
|
||||
if (unboundIndex == valueParameters.size && parameter.defaultValue != null)
|
||||
copyIrElement.copy(parameter.defaultValue!!.expression) as IrExpression
|
||||
else if (!parameter.isVararg) {
|
||||
assert(unboundIndex < valueParameters.size) {
|
||||
"Attempt to use unbound parameter outside of the callee's value parameters"
|
||||
}
|
||||
valueParameters[unboundIndex++].second
|
||||
} else {
|
||||
val elements = mutableListOf<IrVarargElement>()
|
||||
while (unboundIndex < valueParameters.size) {
|
||||
val (param, value) = valueParameters[unboundIndex++]
|
||||
val substitutedParamType = param.type.substitute(superTypeArgumentsMap)
|
||||
if (substitutedParamType == parameter.varargElementType!!)
|
||||
elements += value
|
||||
else
|
||||
elements += IrSpreadElementImpl(expression.startOffset, expression.endOffset, value)
|
||||
}
|
||||
IrVarargImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
parameter.type,
|
||||
parameter.varargElementType!!,
|
||||
elements
|
||||
)
|
||||
}
|
||||
}
|
||||
when (it) {
|
||||
when (parameter) {
|
||||
function.dispatchReceiverParameter ->
|
||||
this.dispatchReceiver = argument.implicitCastIfNeededTo(function.dispatchReceiverParameter!!.type)
|
||||
|
||||
function.extensionReceiverParameter ->
|
||||
this.extensionReceiver = argument.implicitCastIfNeededTo(function.extensionReceiverParameter!!.type)
|
||||
|
||||
else -> putValueArgument(it.index, argument.implicitCastIfNeededTo(function.valueParameters[it.index].type))
|
||||
else -> putValueArgument(parameter.index, argument.implicitCastIfNeededTo(function.valueParameters[parameter.index].type))
|
||||
}
|
||||
}
|
||||
assert(unboundIndex == valueParameters.size) { "Not all arguments of the callee are used" }
|
||||
|
||||
@@ -43,6 +43,8 @@ val IrType.classifierOrNull: IrClassifierSymbol?
|
||||
val IrType.classOrNull: IrClassSymbol?
|
||||
get() = classifierOrNull as? IrClassSymbol
|
||||
|
||||
val IrTypeArgument.typeOrNull: IrType? get() = (this as? IrTypeProjection)?.type
|
||||
|
||||
fun IrType.makeNotNull() =
|
||||
if (this is IrSimpleType && this.hasQuestionMark) {
|
||||
buildSimpleType {
|
||||
|
||||
Reference in New Issue
Block a user