streem / pbandk

Kotlin Code Generator and Runtime for Protocol Buffers
MIT License
271 stars 37 forks source link

Generated `Enum` code causes a Kotlin 2.0.0 compiler error; explicitly pass `hasPresence` argument to workaround #265

Closed darronschall closed 3 months ago

darronschall commented 5 months ago

This is more of a heads-up issue and not necessarily a PBandK issue.

I recently upgraded a project from Kotlin 1.9.23 to Kotlin 2.0.0 and ran into the following compiler error in my generated Protobufs.kt file:

org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering

The stack trace was long, but contained this nested root cause:

Caused by: java.lang.IllegalStateException: Null argument in ExpressionCodegen for parameter VALUE_PARAMETER name:hasPresence index:1 type:kotlin.Boolean
    at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.generateConstructorArguments(ExpressionCodegen.kt:764)
    at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitConstructorCall(ExpressionCodegen.kt:753)
    at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitConstructorCall(ExpressionCodegen.kt:137)
    at org.jetbrains.kotlin.ir.expressions.IrConstructorCall.accept(IrConstructorCall.kt:27)
    ...

I believe this will be fixed in the next version of Kotlin (2.0.10) per https://youtrack.jetbrains.com/issue/KT-68727/K2-Null-argument-in-ExpressionCodegen-for-parameter-VALUEPARAMETER-caused-by-an-enum-class-with-default-parameter-in-a-different

A workaround is to explicitly pass the hasPresence = false argument to pbandk.FieldDescriptor.Type.Enum (instead of relying on the default value of false) in the FieldDescriptor.

That is, for generated code like this:

add(
    pbandk.FieldDescriptor(
        messageDescriptor = this@Companion::descriptor,
        name = "example",
        number = 3,
        type = pbandk.FieldDescriptor.Type.Enum(enumCompanion = com.example.ExampleRequest.Example.Companion),
        jsonName = "example",
        value = com.example.ExampleRequest.example
    )
)

Change the the type = to this:

type = pbandk.FieldDescriptor.Type.Enum(enumCompanion = com.example.ExampleRequest.Example.Companion, hasPresence = false),

PBandK might want to create a new release to update the generated code with this K2 workaround (to always pass the hasPresence argument for enums), but, again, it's not really a PBandK issue and should be fixed in Kotlin 2.0.10.

mikolajefento commented 4 months ago

I have also experienced this issue. The workaround helped, thank you very much 🙌 I hope that it will be fixed when library will support K2 officially

garyp commented 4 months ago

Thanks for the workaround @darronschall and the pointer to the upstream issue! I have a branch in progress right now to update pbandk to Kotlin 2.0.0 and just ran into this bug as well. I see that 2.0.10 is already at the RC stage, so hopefully it'll be released very soon. But if it isn't then I can make a pbandk release with your workaround applied.

garyp commented 3 months ago

FYI this was fixed in https://github.com/streem/pbandk/pull/270. It'll be part of the next pbandk release (which I'm aiming to do soon).