How to create an inlined property setter?


#1

In the example below, the first line of foo creates a clean inlined getter from a property reference Object::x.
How can I achieve the same for a setter in a concise way? Neither Object::x nor Object::x.setter work.

class Object {
    var x: Int = 0

    inline fun <T> inlineGetter(getter: (Object) -> T): T {
        return getter(this)
    }

    inline fun <T> inlineSetter(setter: (Object, T) -> Void, value: T): T {
        setter(this, value)
        return value
    }

    fun foo() {
        val a = inlineGetter(Object::x)
        val b = inlineSetter(Object::x, 1)      // does not work!
    }
} 

#2

If you use -> Unit instead of -> Void, Object::x.setter seems to work…


#3

@mslenc ok, with -> Unit it will compile

However, it does not work as expected.
The getter will create a clean GETFIELD instruction, which (after optimization) should burn down to:

    ALOAD 0
    CHECKCAST .../Object
    GETFIELD .../Object.x : I

The setter however will load the KMutualProperty, lookup the setter, box the integer, invoke the setter (function) and unbox the integer again:

    ALOAD 0
    ASTORE 3
    GETSTATIC .../Object$foo$b$1.INSTANCE : Lkotlin/reflect/KMutableProperty1;
    INVOKEINTERFACE kotlin/reflect/KMutableProperty1.getSetter ()Lkotlin/reflect/KMutableProperty1$Setter;
    CHECKCAST kotlin/jvm/functions/Function2
    ASTORE 4
    ICONST_1
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    ASTORE 5
    ALOAD 4
    ALOAD 3
    ALOAD 5
    INVOKEINTERFACE kotlin/jvm/functions/Function2.invoke (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
    POP
    ALOAD 5
    CHECKCAST java/lang/Number
    INVOKEVIRTUAL java/lang/Number.intValue ()I
    ISTORE 2

What I want is a replacement for val b = inlineSetter({ o: Object, i: Int -> o.x = i}, 1), which is clearly too much boilerplate but compiles to the expected PUTFIELD:

    ALOAD 0
    ASTORE 3
    ICONST_1
    ISTORE 4
    ALOAD 3
    ILOAD 4
    ISTORE 5
    CHECKCAST org/tango42/music/ui/util/Object
    ASTORE 6
    ALOAD 6
    ILOAD 5
    PUTFIELD .../Object.x : I
    ILOAD 4
    ISTORE 2