Support anonymous function as inline parameters

This commit is contained in:
Mikhael Bogdanov
2019-04-08 11:21:16 +02:00
parent 2a3a9bb5fc
commit 10e3dfa980
4 changed files with 32 additions and 24 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.inline.*
@@ -12,9 +13,11 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.util.getArguments
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlineParameter
import org.jetbrains.kotlin.utils.keysToMap
import org.jetbrains.org.objectweb.asm.Type
@@ -150,4 +153,20 @@ class IrExpressionLambdaImpl(
}
fun isInlineIrExpression(argumentExpression: IrExpression) =
argumentExpression is IrBlock && argumentExpression.origin == IrStatementOrigin.LAMBDA
argumentExpression is IrBlock &&
(argumentExpression.origin == IrStatementOrigin.LAMBDA || argumentExpression.origin == IrStatementOrigin.ANONYMOUS_FUNCTION)
fun IrFunction.isInlineFunctionCall(context: JvmBackendContext) =
(!context.state.isInlineDisabled || typeParameters.any { it.isReified }) &&
(isInline || isArrayConstructorWithLambda())
private fun IrFunction.isArrayConstructorWithLambda() =
valueParameters.size == 2 &&
this is IrConstructor &&
parentAsClass.let {
it.getPackageFragment()?.fqName?.asString() == "kotlin" &&
it.name.asString().endsWith("Array")
}
fun IrValueParameter.isInlineParameter() =
!isNoinline && !type.isNullable() && type.isFunctionOrKFunction()
@@ -28,7 +28,9 @@ import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineParameter
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
@@ -83,7 +85,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
override fun visitCall(expression: IrCall): IrExpression {
val callee = expression.symbol.owner
if (callee.isInlineFunction(context)) {
if (callee.isInlineFunctionCall(context)) {
//TODO: more wise filtering
callee.valueParameters.forEach { valueParameter ->
if (valueParameter.isInlineParameter()) {
@@ -589,22 +591,6 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
}
// TODO: Move to IrUtils
private fun IrFunction.isInlineFunction(context: JvmBackendContext) =
(!context.state.isInlineDisabled || typeParameters.any { it.isReified }) &&
(isInline || isArrayConstructorWithLambda())
private fun IrFunction.isArrayConstructorWithLambda() =
valueParameters.size == 2 &&
this is IrConstructor &&
parentAsClass.let {
it.getPackageFragment()?.fqName?.asString() == "kotlin" &&
it.name.asString().endsWith("Array")
}
private fun IrValueParameter.isInlineParameter() =
!isNoinline && !type.isNullable() && type.isFunctionOrKFunction()
private fun IrType.substitute(substitutionMap: Map<IrTypeParameter, IrType>): IrType {
if (this !is IrSimpleType) return this
@@ -8,12 +8,16 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineCall
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrContainerExpression
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.util.isFunction
import org.jetbrains.kotlin.ir.util.isNullable
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -32,12 +36,12 @@ private class RemoveDeclarationsThatWouldBeInlinedLowering(val context: JvmBacke
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
val owner = expression.symbol.owner
if (expression.descriptor.isInlineCall(context.state)) {
if (expression.symbol.owner.isInlineFunctionCall(context)) {
owner.valueParameters.filter {
!it.isNoinline && it.type.isFunction() && !it.type.isNullable()
}.forEach {
val valueArgument = expression.getValueArgument(it.index) as? IrContainerExpression ?: return@forEach
if (valueArgument.origin == IrStatementOrigin.LAMBDA) {
if (isInlineIrExpression(valueArgument)) {
val reference =
valueArgument.statements.firstIsInstanceOrNull<IrFunctionReference>() ?: return@forEach
loweredLambdasToDelete.add(reference.symbol.owner)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt
package test