JVM_IR indy-SAM conversions: prohibit in crossinline lambdas

KT-44278 KT-26060 KT-42621
This commit is contained in:
Dmitry Petrov
2021-01-27 15:39:48 +03:00
parent ad1d80d700
commit f0abd8bc68
16 changed files with 317 additions and 149 deletions
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.load.java.JvmAbi
internal val fakeInliningLocalVariablesLowering = makeIrFilePhase(
@@ -56,16 +57,22 @@ internal class FakeInliningLocalVariablesLowering(val context: JvmBackendContext
}
private fun IrFunction.addFakeLocalVariable(name: String) {
val oldBody = body
context.createIrBuilder(symbol).run {
body = irBlockBody {
// Create temporary variable, but make sure it's origin is `DEFINED` so that
// it will materialize in the code.
// Also, do not forget to remove $$forInline suffix, otherwise, IDE will not be able to navigate to inline function.
createTmpVariable(irInt(0), name.removeSuffix(FOR_INLINE_SUFFIX), origin = IrDeclarationOrigin.DEFINED)
if (body is IrExpressionBody) {
+irReturn((body as IrExpressionBody).expression)
} else {
(body as IrBlockBody).statements.forEach { +it }
when (oldBody) {
is IrExpressionBody -> {
+irReturn(oldBody.expression)
}
is IrBlockBody ->
oldBody.statements.forEach { +it }
else -> {
throw AssertionError("Unexpected body:\n${this@addFakeLocalVariable.dump()}")
}
}
}
}
@@ -45,6 +45,8 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
// function reference classes needed.
private val ignoredFunctionReferences = mutableSetOf<IrCallableReference<*>>()
private val inlineLambdaToValueParameter = HashMap<IrFunction, IrValueParameter>()
private val IrFunctionReference.isIgnored: Boolean
get() = (!type.isFunctionOrKFunction() && !isSuspendFunctionReference()) || ignoredFunctionReferences.contains(this)
@@ -56,7 +58,20 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
(origin == null || origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE || origin == IrStatementOrigin.SUSPEND_CONVERSION)
override fun lower(irFile: IrFile) {
ignoredFunctionReferences.addAll(IrInlineReferenceLocator.scan(context, irFile))
irFile.accept(
object : IrInlineReferenceLocator(context) {
override fun visitInlineLambda(
argument: IrFunctionReference,
callee: IrFunction,
parameter: IrValueParameter,
scope: IrDeclaration
) {
ignoredFunctionReferences.add(argument)
inlineLambdaToValueParameter[argument.symbol.owner] = parameter
}
},
null
)
irFile.transformChildrenVoid(this)
}
@@ -137,12 +152,21 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
return false
// Can't use indy-based SAM conversion inside inline fun (Ok in inline lambda).
if (target.parents.any { it is IrSimpleFunction && it.isInline && it.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA })
if (target.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() })
return false
return true
}
private fun IrDeclarationParent.isInlineFunction() =
this is IrSimpleFunction && isInline && origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
private fun IrDeclarationParent.isCrossinlineLambda(): Boolean {
val irFun = this as? IrSimpleFunction ?: return false
return origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA &&
inlineLambdaToValueParameter[irFun]?.isCrossinline == true
}
private fun IrType.isProhibitedTypeForIndySamConversion(): Boolean {
if (this !is IrSimpleType) return false
@@ -221,6 +221,7 @@ private fun IrSimpleFunction.createMultifileDelegateIfNeeded(
if (DescriptorVisibilities.isPrivate(originalVisibility) ||
name == StaticInitializersLowering.clinitName ||
origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR ||
origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA ||
// $annotations methods in the facade are only needed for const properties.
(origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS &&
(metadata as? MetadataSource.Property)?.isConst != true)