[K/N] Fix work with adapted function references

Their parsing was totally incorrect for K2, and sometimes incorrect for
K1. After this commit it uses same code as for JVM.

^KT-55462
This commit is contained in:
Pavel Kunyavskiy
2023-01-24 12:42:19 +01:00
committed by Space Team
parent 9a693fa967
commit cb655d2d37
25 changed files with 292 additions and 32 deletions
@@ -463,6 +463,8 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
private val useOptimizedSuperClass =
context.state.generateOptimizedCallableReferenceSuperClasses
// This code is partially duplicated in IrUtils getAdapteeFromAdaptedForReferenceFunction
// The difference is utils version supports ReturnableBlock, but returns called function instead of call node.
private val adapteeCall: IrFunctionAccessExpression? =
if (callee.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) {
// The body of a callable reference adapter contains either only a call, or an IMPLICIT_COERCION_TO_UNIT type operator
@@ -1368,3 +1368,24 @@ val IrFunction.isValueClassTypedEquals: Boolean
&& contextReceiverParametersCount == 0 && extensionReceiverParameter == null
&& (parentClass.isValue)
}
// This code is partially duplicated in jvm FunctionReferenceLowering::adapteeCall
// The difference is jvm version doesn't support ReturnableBlock, but returns call node instead of called function.
fun IrFunction.getAdapteeFromAdaptedForReferenceFunction() : IrFunction? {
if (origin != IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) return null
// The body of a callable reference adapter contains either only a call, or an IMPLICIT_COERCION_TO_UNIT type operator
// applied to a either a call or ReturnableBlock produced from that call inlining.
// That call's target is the original function which we need to get.
fun unknownStructure(): Nothing = throw UnsupportedOperationException("Unknown structure of ADAPTER_FOR_CALLABLE_REFERENCE: ${dump()}")
val call = when (val statement = body?.statements?.singleOrNull() ?: unknownStructure()) {
is IrTypeOperatorCall -> {
if (statement.operator != IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) unknownStructure()
statement.argument
}
is IrReturn -> statement.value
else -> statement
}
if (call is IrReturnableBlock) return (call.inlineFunctionSymbol ?: unknownStructure()).owner
if (call !is IrFunctionAccessExpression) { unknownStructure() }
return call.symbol.owner
}