[IR] Inliner: supported tricky function references

This includes references to functions with varargs and default arguments
This commit is contained in:
Igor Chevdar
2019-12-18 17:24:55 +03:00
parent cdf9ef63ba
commit 7a5e8b4316
2 changed files with 45 additions and 13 deletions
@@ -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 {