Repository: JetBrains/kotlin
File: compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt (Kotlin)

Code before:
        if (!isCallOfFunctionInCorrespondingDefaultDispatch)
            return super.inlineCall(nodeAndSmap, inlineDefaultLambda, isCallOfFunctionInCorrespondingDefaultDispatch)

        // The call to a function in its corresponding $default handler is inlined verbatim in the JVM BE, so for compatibility
        // we have to do the same here. The code below is mostly copied from InlineCodegenForDefaultBody.kt.
        val childSourceMapper = SourceMapCopier(sourceCompiler.lazySourceMapper, nodeAndSmap.classSMAP)

        val node = nodeAndSmap.node
        val transformedMethod = MethodNode(
            node.access,
            node.name,
            node.desc,
            node.signature,
            node.exceptions.toTypedArray()
        )

        val argsSize =
            (Type.getArgumentsAndReturnSizes(jvmSignature.asmMethod.descriptor) ushr 2) - if (function.isStatic) 1 else 0
        node.accept(object : InlineAdapter(transformedMethod, 0, childSourceMapper) {
            override fun visitLocalVariable(name: String, desc: String, signature: String?, start: Label, end: Label, index: Int) {
                // We only copy LVT entries for local variables, since we already generated entries for the method parameters,
                if (index >= argsSize) super.visitLocalVariable(name, desc, signature, start, end, index)
            }
        })

        transformedMethod.accept(MethodBodyVisitor(codegen.visitor))

        return InlineResult.create()
    }
}

class IrExpressionLambdaImpl(
    val reference: IrFunctionReference,
    val function: IrFunction,
    private val typeMapper: IrTypeMapper,
    methodSignatureMapper: MethodSignatureMapper,
    context: JvmBackendContext,
    isCrossInline: Boolean,
    override val isBoundCallableReference: Boolean,
    override val isExtensionLambda: Boolean
) : ExpressionLambda(isCrossInline), IrExpressionLambda {

    override val isSuspend: Boolean = function.isSuspend

    override fun isReturnFromMe(labelName: String): Boolean {
        return false //always false
    }

    // This name doesn't actually matter: it is used internally to tell this lambda's captured
    // arguments apart from any other scope's. So long as it's unique, any value is fine.
    // This particular string slightly aids in debugging internal compiler errors as it at least

Review comment (suggestion):
Looks equivalent to just passing `MethodBodyVisitor` to `InlineAdapter`. (I don't think you need `InlineAdapter` here at all - simply overriding `visitLineNumber` to do `super.visitLineNumber(childSourceMapper.mapLineNumber(line), start)` should be enough)

Code after:
        context.getLocalClassType(reference) ?: throw AssertionError("callable reference ${reference.dump()} has no name in context")

    private val capturedParameters: Map<CapturedParamDesc, IrValueParameter> =
        reference.getArgumentsWithIr().associate { (param, _) ->
            capturedParamDesc(param.name.asString(), typeMapper.mapType(param.type)) to param
        }

    override val capturedVars: List<CapturedParamDesc> = capturedParameters.keys.toList()

    private val loweredMethod = methodSignatureMapper.mapAsmMethod(function)

    val capturedParamsInDesc: List<Type> = if (isBoundCallableReference) {
        loweredMethod.argumentTypes.take(1)
    } else loweredMethod.argumentTypes.drop(if (isExtensionLambda) 1 else 0).take(capturedVars.size)

    override val invokeMethod: Method = loweredMethod.let {
        Method(
            it.name,
            it.returnType,
            (if (isBoundCallableReference) it.argumentTypes.drop(1)
            else (if (isExtensionLambda) it.argumentTypes.take(1) else emptyList()) +
                    it.argumentTypes.drop((if (isExtensionLambda) 1 else 0) + capturedVars.size)).toTypedArray()
        )
    }

    // Need the descriptor without captured parameters here.
    override val invokeMethodDescriptor: FunctionDescriptor = function.originalFunction.toIrBasedDescriptor()

    override val hasDispatchReceiver: Boolean = false

    override fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor = function.toIrBasedDescriptor()

    override fun isCapturedSuspend(desc: CapturedParamDesc): Boolean =
        capturedParameters[desc]?.let { it.isInlineParameter() && it.type.isSuspendFunctionTypeOrSubtype() } == true
}

class IrDefaultLambda(
    lambdaClassType: Type,
    capturedArgs: Array<Type>,
    private val irValueParameter: IrValueParameter,
    offset: Int,
    needReification: Boolean
) : DefaultLambda(
    lambdaClassType, capturedArgs, irValueParameter.toIrBasedDescriptor() as ValueParameterDescriptor, offset, needReification
) {

    override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method {
        val invoke =
            irValueParameter.type.classOrNull!!.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "invoke" }
        return (sourceCompiler as IrSourceCompilerForInline).codegen.context.methodSignatureMapper.mapSignatureSkipGeneric(invoke).asmMethod
    }