Fix for KT-26164 (#1954)
This commit is contained in:
+19
-22
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.ir.IrStatement
|
|||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.declarations.getDefault
|
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
@@ -34,11 +34,9 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
|||||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.util.irCall
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
@@ -313,12 +311,12 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private class ParameterToArgument(val parameterDescriptor: ParameterDescriptor,
|
private class ParameterToArgument(val parameter: IrValueParameter,
|
||||||
val argumentExpression : IrExpression) {
|
val argumentExpression : IrExpression) {
|
||||||
|
|
||||||
val isInlinableLambdaArgument : Boolean
|
val isInlinableLambdaArgument : Boolean
|
||||||
get() {
|
get() {
|
||||||
if (!InlineUtil.isInlineParameter(parameterDescriptor)) return false
|
if (!InlineUtil.isInlineParameter(parameter.descriptor)) return false
|
||||||
if (argumentExpression is IrFunctionReference
|
if (argumentExpression is IrFunctionReference
|
||||||
&& !argumentExpression.descriptor.isSuspend) return true // Skip suspend functions for now since it's not supported by FE anyway.
|
&& !argumentExpression.descriptor.isSuspend) return true // Skip suspend functions for now since it's not supported by FE anyway.
|
||||||
|
|
||||||
@@ -347,21 +345,20 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
): List<ParameterToArgument> {
|
): List<ParameterToArgument> {
|
||||||
|
|
||||||
val parameterToArgument = mutableListOf<ParameterToArgument>() // Result list.
|
val parameterToArgument = mutableListOf<ParameterToArgument>() // Result list.
|
||||||
val functionDescriptor = irFunction.descriptor.original // Descriptor of function to be called.
|
|
||||||
|
|
||||||
if (irCall.dispatchReceiver != null && // Only if there are non null dispatch receivers both
|
if (irCall.dispatchReceiver != null && // Only if there are non null dispatch receivers both
|
||||||
functionDescriptor.dispatchReceiverParameter != null) // on call site and in function declaration.
|
irFunction.dispatchReceiverParameter != null) // on call site and in function declaration.
|
||||||
parameterToArgument += ParameterToArgument(
|
parameterToArgument += ParameterToArgument(
|
||||||
parameterDescriptor = functionDescriptor.dispatchReceiverParameter!!,
|
parameter = irFunction.dispatchReceiverParameter!!,
|
||||||
argumentExpression = irCall.dispatchReceiver!!
|
argumentExpression = irCall.dispatchReceiver!!
|
||||||
)
|
)
|
||||||
|
|
||||||
val valueArguments =
|
val valueArguments =
|
||||||
irCall.descriptor.valueParameters.map { irCall.getValueArgument(it) }.toMutableList()
|
irCall.descriptor.valueParameters.map { irCall.getValueArgument(it) }.toMutableList()
|
||||||
|
|
||||||
if (functionDescriptor.extensionReceiverParameter != null) {
|
if (irFunction.extensionReceiverParameter != null) {
|
||||||
parameterToArgument += ParameterToArgument(
|
parameterToArgument += ParameterToArgument(
|
||||||
parameterDescriptor = functionDescriptor.extensionReceiverParameter!!,
|
parameter = irFunction.extensionReceiverParameter!!,
|
||||||
argumentExpression = if (irCall.extensionReceiver != null) {
|
argumentExpression = if (irCall.extensionReceiver != null) {
|
||||||
irCall.extensionReceiver!!
|
irCall.extensionReceiver!!
|
||||||
} else {
|
} else {
|
||||||
@@ -376,25 +373,25 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
|
|
||||||
val parametersWithDefaultToArgument = mutableListOf<ParameterToArgument>()
|
val parametersWithDefaultToArgument = mutableListOf<ParameterToArgument>()
|
||||||
irFunction.valueParameters.forEach { parameter -> // Iterate value parameters.
|
irFunction.valueParameters.forEach { parameter -> // Iterate value parameters.
|
||||||
val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor
|
val argument = valueArguments[parameter.index] // Get appropriate argument from call site.
|
||||||
val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site.
|
|
||||||
when {
|
when {
|
||||||
argument != null -> { // Argument is good enough.
|
argument != null -> { // Argument is good enough.
|
||||||
parameterToArgument += ParameterToArgument( // Associate current parameter with the argument.
|
parameterToArgument += ParameterToArgument( // Associate current parameter with the argument.
|
||||||
parameterDescriptor = parameterDescriptor,
|
parameter = parameter,
|
||||||
argumentExpression = argument
|
argumentExpression = argument
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterDescriptor.hasDefaultValue() -> { // There is no argument - try default value.
|
// After ExpectDeclarationsRemoving pass default values from expect declarations
|
||||||
val defaultArgument = irFunction.getDefault(parameterDescriptor)!!
|
// are represented correctly in IR.
|
||||||
|
parameter.defaultValue != null -> { // There is no argument - try default value.
|
||||||
parametersWithDefaultToArgument += ParameterToArgument(
|
parametersWithDefaultToArgument += ParameterToArgument(
|
||||||
parameterDescriptor = parameterDescriptor,
|
parameter = parameter,
|
||||||
argumentExpression = defaultArgument.expression
|
argumentExpression = parameter.defaultValue!!.expression
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterDescriptor.varargElementType != null -> {
|
parameter.varargElementType != null -> {
|
||||||
val emptyArray = IrVarargImpl(
|
val emptyArray = IrVarargImpl(
|
||||||
startOffset = irCall.startOffset,
|
startOffset = irCall.startOffset,
|
||||||
endOffset = irCall.endOffset,
|
endOffset = irCall.endOffset,
|
||||||
@@ -402,14 +399,14 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
varargElementType = parameter.varargElementType!!
|
varargElementType = parameter.varargElementType!!
|
||||||
)
|
)
|
||||||
parameterToArgument += ParameterToArgument(
|
parameterToArgument += ParameterToArgument(
|
||||||
parameterDescriptor = parameterDescriptor,
|
parameter = parameter,
|
||||||
argumentExpression = emptyArray
|
argumentExpression = emptyArray
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val message = "Incomplete expression: call to $functionDescriptor " +
|
val message = "Incomplete expression: call to ${irFunction.descriptor} " +
|
||||||
"has no argument at index ${parameterDescriptor.index}"
|
"has no argument at index ${parameter.index}"
|
||||||
throw Error(message)
|
throw Error(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -428,7 +425,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
val evaluationStatements = mutableListOf<IrStatement>() // List of evaluation statements.
|
val evaluationStatements = mutableListOf<IrStatement>() // List of evaluation statements.
|
||||||
val substitutor = ParameterSubstitutor()
|
val substitutor = ParameterSubstitutor()
|
||||||
parameterToArgumentOld.forEach {
|
parameterToArgumentOld.forEach {
|
||||||
val parameterDescriptor = it.parameterDescriptor
|
val parameterDescriptor = it.parameter.descriptor
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to create temporary variable for each argument except inlinable lambda arguments.
|
* We need to create temporary variable for each argument except inlinable lambda arguments.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ fun box() {
|
|||||||
Test5().Inner().test()
|
Test5().Inner().test()
|
||||||
|
|
||||||
42.test6()
|
42.test6()
|
||||||
|
assertEquals(inlineFunction("OK"), "OK,0,null")
|
||||||
}
|
}
|
||||||
|
|
||||||
expect fun test1(x: Int = 42): Int
|
expect fun test1(x: Int = 42): Int
|
||||||
@@ -66,3 +67,9 @@ expect fun Int.test6(arg: Int = this)
|
|||||||
actual fun Int.test6(arg: Int) {
|
actual fun Int.test6(arg: Int) {
|
||||||
assertEquals(arg, this)
|
assertEquals(arg, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default parameter in inline function.
|
||||||
|
expect inline fun inlineFunction(a: String, b: Int = 0, c: () -> Double? = { null }): String
|
||||||
|
|
||||||
|
actual inline fun inlineFunction(a: String, b: Int, c: () -> Double?): String = a + "," + b + "," + c()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user