JVM_IR: support function references with default parameters
This commit is contained in:
@@ -231,7 +231,8 @@ private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter) {
|
||||
fun IrFunction.copyValueParametersToStatic(
|
||||
source: IrFunction,
|
||||
origin: IrDeclarationOrigin,
|
||||
dispatchReceiverType: IrType? = source.dispatchReceiverParameter?.type
|
||||
dispatchReceiverType: IrType? = source.dispatchReceiverParameter?.type,
|
||||
numValueParametersToCopy: Int = source.valueParameters.size
|
||||
) {
|
||||
val target = this
|
||||
assert(target.valueParameters.isEmpty())
|
||||
@@ -266,6 +267,7 @@ fun IrFunction.copyValueParametersToStatic(
|
||||
}
|
||||
|
||||
for (oldValueParameter in source.valueParameters) {
|
||||
if (oldValueParameter.index >= numValueParametersToCopy) break
|
||||
target.valueParameters.add(
|
||||
oldValueParameter.copyTo(
|
||||
target,
|
||||
|
||||
@@ -141,7 +141,7 @@ private val defaultArgumentInjectorPhase = makeIrFilePhase(
|
||||
::JvmDefaultParameterInjector,
|
||||
name = "DefaultParameterInjector",
|
||||
description = "Transform calls with default arguments into calls to stubs",
|
||||
prerequisite = setOf(defaultArgumentStubPhase, callableReferencePhase)
|
||||
prerequisite = setOf(defaultArgumentStubPhase, callableReferencePhase, inlineCallableReferenceToLambdaPhase)
|
||||
)
|
||||
|
||||
private val interfacePhase = makeIrFilePhase(
|
||||
|
||||
+25
-3
@@ -27,8 +27,11 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.isSubtypeOf
|
||||
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -141,7 +144,24 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
|
||||
val irBuilder =
|
||||
context.createIrBuilder(scope.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
|
||||
|
||||
|
||||
val boundReceiver = expression.dispatchReceiver ?: expression.extensionReceiver
|
||||
|
||||
val expectedType = expression.type
|
||||
var expectedNumValueParameters: Int
|
||||
if (expectedType.isFunctionOrKFunction() || expectedType.isSuspendFunction() || expectedType.isKSuspendFunction()) { // TODO: handle subtypes
|
||||
expectedNumValueParameters = (expectedType as IrSimpleType).arguments.size - 1 // In ...Function classes, the last argument is return type
|
||||
referencedFunction.dispatchReceiverParameter?.let { expectedNumValueParameters-- }
|
||||
referencedFunction.extensionReceiverParameter?.let { expectedNumValueParameters-- }
|
||||
boundReceiver?.let { expectedNumValueParameters++ }
|
||||
assert(referencedFunction.valueParameters.subList(expectedNumValueParameters, referencedFunction.valueParameters.size).all {
|
||||
it.defaultValue != null
|
||||
})
|
||||
} else {
|
||||
assert(expectedType.classOrNull?.isSubtypeOfClass(context.irBuiltIns.kPropertyClass) == true)
|
||||
expectedNumValueParameters = 0
|
||||
}
|
||||
|
||||
return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) {
|
||||
lateinit var variableForBoundReceiver: IrVariable
|
||||
if (boundReceiver != null) {
|
||||
@@ -161,9 +181,10 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
|
||||
}
|
||||
copyTypeParametersFrom(referencedFunction)
|
||||
if (boundReceiver == null) {
|
||||
copyValueParametersToStatic(referencedFunction, origin)
|
||||
copyValueParametersToStatic(referencedFunction, origin, numValueParametersToCopy = expectedNumValueParameters)
|
||||
} else {
|
||||
for (oldValueParameter in referencedFunction.valueParameters) {
|
||||
if (oldValueParameter.index >= expectedNumValueParameters) break
|
||||
valueParameters.add(
|
||||
oldValueParameter.copyTo(
|
||||
this,
|
||||
@@ -197,6 +218,7 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
|
||||
}
|
||||
|
||||
for (it in referencedFunction.valueParameters.indices) {
|
||||
if (it >= expectedNumValueParameters) break
|
||||
call.putValueArgument(it, irGet(valueParameters[shift++]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
inline fun String.app(f: (String) -> String) = f(this)
|
||||
|
||||
fun fff(s: String, n: Int = 42) = s
|
||||
|
||||
fun box() = "OK".app(::fff)
|
||||
+5
@@ -8982,6 +8982,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/protected.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referenceAsArg.kt")
|
||||
public void testReferenceAsArg() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFromOtherFile.kt")
|
||||
public void testSimpleFromOtherFile() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
||||
|
||||
+5
@@ -8982,6 +8982,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/protected.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referenceAsArg.kt")
|
||||
public void testReferenceAsArg() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFromOtherFile.kt")
|
||||
public void testSimpleFromOtherFile() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
||||
|
||||
+5
@@ -7867,6 +7867,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/protected.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referenceAsArg.kt")
|
||||
public void testReferenceAsArg() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFromOtherFile.kt")
|
||||
public void testSimpleFromOtherFile() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
||||
|
||||
Generated
+5
@@ -6717,6 +6717,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/protected.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referenceAsArg.kt")
|
||||
public void testReferenceAsArg() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFromOtherFile.kt")
|
||||
public void testSimpleFromOtherFile() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
||||
|
||||
+5
@@ -7802,6 +7802,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/protected.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referenceAsArg.kt")
|
||||
public void testReferenceAsArg() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/referenceAsArg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFromOtherFile.kt")
|
||||
public void testSimpleFromOtherFile() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
||||
|
||||
Reference in New Issue
Block a user