Running into a weird issue where if I use kotlin S...
# compiler
m
Running into a weird issue where if I use kotlin SAM types my code compiles but crashes at runtime because the lambda can't be cast to the java SAM type, but using java SAM types in my IR generation causes
Copy code
Unexpected IR element found during code generation. Either code generation for it is not implemented, or it should have been lowered:
FUNCTION_REFERENCE 'private final fun _init_$0 (receiver: com.martmists.serialization.TestData): <http://kotlin.Int|kotlin.Int> declared in com.martmists.serialization.TestData.Companion' type=@[FlexibleNullability] java.util.function.Function<@[FlexibleNullability] O of com.mojang.serialization.MapCodec.forGetter?, @[FlexibleNullability] A of com.mojang.serialization.MapCodec?>? origin=LAMBDA reflectionTarget=null
What am I doing wrong? Pastebin link: https://pastebin.com/FCSX76GE (uses kotlin types, and crashes when the lambda is cast to Function)
l
I made this helper once:
Copy code
fun IrBuilderWithScope.irLambdaWithSamConversion(samType: IrType, builder: IrSimpleFunction.(DeclarationIrBuilder) -> Unit): IrTypeOperatorCallImpl {
    val parent = scope.getLocalDeclarationParent()
    val function = context.irBuiltIns.irFactory.buildFun {
        startOffset = parent.startOffset
        endOffset = parent.endOffset
        origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
        name = Name.identifier("")
        returnType = context.irBuiltIns.unitType
        visibility = DescriptorVisibilities.LOCAL
    }

    function.parent = parent
    function.builder(context.irBuiltIns.createIrBuilder(function.symbol))

    return irFunctionAsSamLambda(startOffset, endOffset, context.irBuiltIns, function, samType)
}

fun irFunctionAsSamLambda(
    startOffset: Int,
    endOffset: Int,
    irBuiltIns: IrBuiltIns,
    function: IrSimpleFunction,
    type: IrType,
): IrTypeOperatorCallImpl {
    val functionType = irBuiltIns.getKFunctionType(function.returnType, function.parameters.map { it.type })

    return IrTypeOperatorCallImpl(
        startOffset,
        endOffset,
        type,
        IrTypeOperator.SAM_CONVERSION,
        type,
        IrFunctionExpressionImpl(
            startOffset,
            endOffset,
            functionType,
            function,
            IrStatementOrigin.LAMBDA,
        ),
    )
}
My guess is that wrapping the call in an
IrTypeOperatorCallImpl
for
IrTypeOperator.SAM_CONVERSION
is the important difference 🤔
Used like:
Copy code
irLambdaWithSamConversion(wiringFactory) { builder ->
    val origin = addValueParameter("origin", originType)

    returnType = componentType
    body = builder.irBlockBody {
        // ...
    }
}