I have a property delegate using a context receiver:
class LoggingPropertyDelegate<T, V, L : Log>(
private var value: V,
private val toLog: T.() -> L
) : ReadWriteProperty<T, V> {
override fun getValue(thisRef: T, property: KProperty<*>) = value
context(Logger)
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
this.value = value
log(toLog(thisRef))
}
}
But when I try to use it on a property:
var myValue: Int by LoggingPropertyDelegate(0, { InfoLog("Changed to $myValue") })
I get an error that there is no suitable set functions for the delegate. If I remove the context from the method everything works as expected.
Is it not possible to use context receivers on property delegates?
It is possible to use a property delegate that has context receivers. You just need to provide the context receiver in some way.
First, note that you should put
context(Logger)on the delegate class type, not onsetValue:If
myValueis an instance property of some classFoo, then you can do:Note that if
Foois a data class, there seems to be a compiler bug that causes the compiler to crash. Perhaps context receivers are lowered to extra compiler parameters (?)And then when instantiating
Foo, you will need to provide aLogger:(or instantiate
Fooin another function with aLoggercontext receiver, of course)If
myValueis a local variable, you can also directly usewithto introduce the context receiver instance, in addition to adding aLoggercontext receiver to the enclosing function.