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(
|
fun IrFunction.copyValueParametersToStatic(
|
||||||
source: IrFunction,
|
source: IrFunction,
|
||||||
origin: IrDeclarationOrigin,
|
origin: IrDeclarationOrigin,
|
||||||
dispatchReceiverType: IrType? = source.dispatchReceiverParameter?.type
|
dispatchReceiverType: IrType? = source.dispatchReceiverParameter?.type,
|
||||||
|
numValueParametersToCopy: Int = source.valueParameters.size
|
||||||
) {
|
) {
|
||||||
val target = this
|
val target = this
|
||||||
assert(target.valueParameters.isEmpty())
|
assert(target.valueParameters.isEmpty())
|
||||||
@@ -266,6 +267,7 @@ fun IrFunction.copyValueParametersToStatic(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (oldValueParameter in source.valueParameters) {
|
for (oldValueParameter in source.valueParameters) {
|
||||||
|
if (oldValueParameter.index >= numValueParametersToCopy) break
|
||||||
target.valueParameters.add(
|
target.valueParameters.add(
|
||||||
oldValueParameter.copyTo(
|
oldValueParameter.copyTo(
|
||||||
target,
|
target,
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ private val defaultArgumentInjectorPhase = makeIrFilePhase(
|
|||||||
::JvmDefaultParameterInjector,
|
::JvmDefaultParameterInjector,
|
||||||
name = "DefaultParameterInjector",
|
name = "DefaultParameterInjector",
|
||||||
description = "Transform calls with default arguments into calls to stubs",
|
description = "Transform calls with default arguments into calls to stubs",
|
||||||
prerequisite = setOf(defaultArgumentStubPhase, callableReferencePhase)
|
prerequisite = setOf(defaultArgumentStubPhase, callableReferencePhase, inlineCallableReferenceToLambdaPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val interfacePhase = makeIrFilePhase(
|
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.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
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.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -141,7 +144,24 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
|
|||||||
val irBuilder =
|
val irBuilder =
|
||||||
context.createIrBuilder(scope.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
|
context.createIrBuilder(scope.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
|
||||||
|
|
||||||
|
|
||||||
val boundReceiver = expression.dispatchReceiver ?: expression.extensionReceiver
|
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) {
|
return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) {
|
||||||
lateinit var variableForBoundReceiver: IrVariable
|
lateinit var variableForBoundReceiver: IrVariable
|
||||||
if (boundReceiver != null) {
|
if (boundReceiver != null) {
|
||||||
@@ -161,9 +181,10 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
|
|||||||
}
|
}
|
||||||
copyTypeParametersFrom(referencedFunction)
|
copyTypeParametersFrom(referencedFunction)
|
||||||
if (boundReceiver == null) {
|
if (boundReceiver == null) {
|
||||||
copyValueParametersToStatic(referencedFunction, origin)
|
copyValueParametersToStatic(referencedFunction, origin, numValueParametersToCopy = expectedNumValueParameters)
|
||||||
} else {
|
} else {
|
||||||
for (oldValueParameter in referencedFunction.valueParameters) {
|
for (oldValueParameter in referencedFunction.valueParameters) {
|
||||||
|
if (oldValueParameter.index >= expectedNumValueParameters) break
|
||||||
valueParameters.add(
|
valueParameters.add(
|
||||||
oldValueParameter.copyTo(
|
oldValueParameter.copyTo(
|
||||||
this,
|
this,
|
||||||
@@ -197,6 +218,7 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (it in referencedFunction.valueParameters.indices) {
|
for (it in referencedFunction.valueParameters.indices) {
|
||||||
|
if (it >= expectedNumValueParameters) break
|
||||||
call.putValueArgument(it, irGet(valueParameters[shift++]))
|
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");
|
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")
|
@TestMetadata("simpleFromOtherFile.kt")
|
||||||
public void testSimpleFromOtherFile() throws Exception {
|
public void testSimpleFromOtherFile() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
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");
|
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")
|
@TestMetadata("simpleFromOtherFile.kt")
|
||||||
public void testSimpleFromOtherFile() throws Exception {
|
public void testSimpleFromOtherFile() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
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");
|
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")
|
@TestMetadata("simpleFromOtherFile.kt")
|
||||||
public void testSimpleFromOtherFile() throws Exception {
|
public void testSimpleFromOtherFile() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
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");
|
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")
|
@TestMetadata("simpleFromOtherFile.kt")
|
||||||
public void testSimpleFromOtherFile() throws Exception {
|
public void testSimpleFromOtherFile() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
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");
|
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")
|
@TestMetadata("simpleFromOtherFile.kt")
|
||||||
public void testSimpleFromOtherFile() throws Exception {
|
public void testSimpleFromOtherFile() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
runTest("compiler/testData/codegen/box/defaultArguments/simpleFromOtherFile.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user