JVM_IR: change parameter type computation in InlineCallableReferenceToLambda

The reference type is approximated in Psi2Ir, so we may get Nothing as
a reference type argument. Better look at the arguments of the
referenced function.
This commit is contained in:
Georgy Bronnikov
2020-02-21 20:41:04 +03:00
parent 456139fc5e
commit 963258189a
8 changed files with 56 additions and 4 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ir.allParameters
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
@@ -25,7 +26,6 @@ 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.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
@@ -117,10 +117,20 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
val irBuilder = context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) {
val parameterTypes = (expression.type as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
val argumentTypes = parameterTypes.dropLast(1)
// We find the number of parameters for constructed lambda from the type of the function reference,
// but the actual types have to be copied from referencedFunction; function reference argument type may be too
// specific because of approximation. See compiler/testData/codegen/box/callableReference/function/argumentTypes.kt
val boundReceiver: Pair<IrValueParameter, IrExpression>? = expression.getArgumentsWithIr().singleOrNull()
val nParams = (expression.type as IrSimpleType).arguments.size - 1
var toDropAtStart = 0
if (boundReceiver != null) toDropAtStart++
if (referencedFunction is IrConstructor) toDropAtStart++
val argumentTypes = referencedFunction.allParameters.drop(toDropAtStart).take(nParams).map { parameter ->
parameter.type.substitute(
referencedFunction.typeParameters,
referencedFunction.typeParameters.indices.map { expression.getTypeArgument(it)!! }
)
}
val function = buildFun {
setSourceRange(expression)
@@ -0,0 +1,12 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline fun <TT> id(x: TT): TT = x
inline fun <TT> String.extId(x: TT): String = this
private fun <T> ff(value: T?): String {
// In PSI2IR, the funcref is approximated to Function1<Nothing, Pair<String, T>>
value?.let(::id)
return value?.let("OK"::extId)!!
}
fun box() = ff("arg")
@@ -2186,6 +2186,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference/function"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("argumentTypes.kt")
public void testArgumentTypes() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/argumentTypes.kt");
}
@TestMetadata("booleanNotIntrinsic.kt")
public void testBooleanNotIntrinsic() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");
@@ -2186,6 +2186,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference/function"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("argumentTypes.kt")
public void testArgumentTypes() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/argumentTypes.kt");
}
@TestMetadata("booleanNotIntrinsic.kt")
public void testBooleanNotIntrinsic() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");
@@ -2166,6 +2166,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference/function"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("argumentTypes.kt")
public void testArgumentTypes() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/argumentTypes.kt");
}
@TestMetadata("booleanNotIntrinsic.kt")
public void testBooleanNotIntrinsic() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");
@@ -2166,6 +2166,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference/function"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("argumentTypes.kt")
public void testArgumentTypes() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/argumentTypes.kt");
}
@TestMetadata("booleanNotIntrinsic.kt")
public void testBooleanNotIntrinsic() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");
@@ -1596,6 +1596,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference/function"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("argumentTypes.kt")
public void testArgumentTypes() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/argumentTypes.kt");
}
@TestMetadata("booleanNotIntrinsic.kt")
public void testBooleanNotIntrinsic() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");
@@ -1596,6 +1596,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference/function"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("argumentTypes.kt")
public void testArgumentTypes() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/argumentTypes.kt");
}
@TestMetadata("booleanNotIntrinsic.kt")
public void testBooleanNotIntrinsic() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");