Suspend properties


#1

Does anyone know the reason why properties can not be suspending? My use case is protecting a value with a read/write mutex.
I know about KT-16239, but this just looks to me like the text of the error message is wrong, not the error itself.

I did some digging. The only suspend property I could find is coroutineContext but this is a special inline property which get’s completely replaced by the compiler and just suppresses the error (which sadly does not seem to work for other properties).


#2

Presumably because the getter would return a deferred execution which is not what is expected during property invocation. It is arguable that a get with the suspend modifier might as well be a function instead. Many synchronous paradigms don’t fit with coroutines such as init, var decl, constructor, delegation, etc.

One of the limitations I have found that I would like to see lifted though is the ability to default a parameter on a suspendable function to another suspendable function.


#3

I don’t exactly know what you mean. Where is the difference to a suspend function? In either case you don’t see that it is suspending at the call site.

Properties are a shorthand for writing getter and setter functions so again I don’t see why they should not be allowed to be suspend.

Again I don’t see why they should not work. suspend just adds an additional hidden parameter to the functions, so why should that not work with any of those? Ok I can see that maybe the primary constructor should be not suspended so you can create an instance of a class without using coroutines, but worst case you can use runBlocking.

I’m heavily using coroutines in my program and not being able to use coroutines for some of those things is severely limiting or forces me to to write unnecessary boilerplate code.


#4

True, there aren’t any technical reasons the getter can’t accept a continuation. There are a few quirks such as requiring explicit getters and setters (so you can never accept an override val in, say, a constructor but instead always put get/set since they must be functions). You might have to put the suspend modifier on the val instead of the get/set so that an interface can have suspend val foo: String or suspend var bar: String. I’m racking my brain to come up with other incompatibilities, but since properties are just function calls, there aren’t really any. I say file a YouTrack issue. But I wouldn’t be too surprised if they don’t want to support it and have all the extra work (e.g. no const with suspend, no override suspend val with just a val, forced getter/setter, etc)


#5

How so?

suspend var foo: Int
// generates
private foo: Int
suspend fun getFoo(): Int = foo
suspend fun setFoo(value: Int) { foo = value }

Kotlin always generates getters and setters except for privates.

I’ll guess I do that and probably write up a KEEP after that :slight_smile:


#6

This was based on my understanding of overrides and the current default parameter restriction. For example:

open class Foo {
    open suspend var foo: Int
}

class Bar(override suspend var foo: Int) : Foo()

How does that look on the JVM? On the JVM, <init> is not reentrant due to bytecode validation rules IIRC so constructors will never be able to support suspension and still have traditional interop and JVM representation.


#7

Your right about constructors. I guess one way to solve it would be to split up the constructor into 2 calls. The real constructor and a suspend init function but I can see why this would lead to problems with java. But I mostly care about properties in any case.


I don’t really understand the problem with overrides.


#8

One problem is that Java code can’t access the suspend property, since you could only access it from within a Kotlin coroutine.


#9

java can access suspend properties just like java can access suspend functions.


#10

Well, yes, Java can pass a continuation to the suspend function. So

suspend val foo: Foo

would in Java be

Object getFoo(Continuation<Foo> continuation)

But that’s very different from what a writer of Java code is expecting from a Kotlin property.


#11

I don’t really see the problem. If someone writing java is deciding to use a kotlin library based around coroutines they would have the necessary setup to call suspending functions. It does not matter whether they are getters/setters or normal functions.