Indirectly invoking UByte setter function

I’m having some problems invoking the setter function of a property of the type UByte, as seen in this example code:

class Test {
    private var signedByte: Byte
        get() = 0
        set(_) { /* Whatever */ };

    private var unsignedByte: UByte
        get() = 0u
        set(_) { /* Whatever */ };

    init {
        this::signedByte::set.invoke(0)
        this::unsignedByte::set.invoke(0u)
    }

    companion object {
        @JvmStatic fun main(args: Array<String>) {
            Test()
        }
    }
}

It compiles just fine, but when I run it, the program crashes on the

this::unsignedByte::set.invoke(0u)

line with the error message

Exception in thread "main" java.lang.ClassCastException: java.lang.Byte cannot be cast to kotlin.UByte

while the line before that is exactly the same except for using UByte instead of Byte runs just fine.
Why does this happen?

Not sure exactly why this happens. It looks to me as if something in the magic behind inline classes and unsigned numbers is broken.
My guess is this. The normal set function in the bytecode expects a value of type Byte. Since you are calling it through reflection though you get the situation that the unsinged byte is not represented by a Byte but by the UByte wrapper class. I guess the conversion back to the internal Byte representation is failing here.
This seems like a kotlin bug. You should create an issue here: https://kotl.in/issue

Okay, thanks for the info. I’m new to Kotlin, so I wasn’t sure if this was intended behaviour.

The way inline classes work is that where possible they disappear and revert to the member value. This is what the setter does, so at runtime (in code) it expects a (native) byte. The invoke function however is generic and requires a reference type to be passed (it is defined on KMutableProperty). This is a case where the inline class takes the “safe” route and uses the UByte wrapper. From my perspective this is a case where autoboxing and autoinlining interact in an unexpected (perhaps incorrect) way.

Is there a way to work around this problem? Like explicitly specifying types or calling the setter in another way?

Why not invoke it normally through:

init {
    unsignedByte = 0u
}

I’m passing the properties to a function that returns lambdas, so I can later call those to dynamically set the values of the properties by invoking the setter, kinda like passing a pointer. This approach worked fine for Byte properties, but UByte properties crash. Maybe there’s a better way of going it though.

I tried to play around with your example and the only way I could make it work is creating a dedicated method that takes a UByte and set the unsignedByte field, I don’t think there is another way