Hello, I have an awaitAll() question, I am passing...
# coroutines
f
Hello, I have an awaitAll() question, I am passing it two deferred values of type
Deferred<String>
,
Deferred<Boolean>
and am expecting it to return a List, but the result type seems to be of
List<{Comparable<{Boolean & String}> & java.io.Serializable}>
is there something I am missing here?
j
There's no such thing as a list[string, boolean]
j
If you really want to have both values typed properly, you can also simply await both of them sequentially. It's not 100% equivalent (because if the second fails quickly you'll still wait for the first to complete, which may be needlessly long), but it does the job much better in terms of types:
Copy code
val s = stringDeferred.await()
val b = booleanDeferred.await()
If you still want to return them both as one object, use a dedicated data class (or a
Pair<String, Boolean>
) instead of a list. Lists are meant for homogeneous types of items.
f
@Jacob should of said that better meant just a List, with those two item types inserted.
@Joffrey Thank you for the detailed explanation!
j
I'm sure you got a list with a string and a boolean but the common interfaces between them is a complicated concatenation of comparable and serializable, and that becomes the type of the list
f
@Jacob Correct, unfortunately the function signature would seem like it would return the same type as the deferred, but it seems that is not that case.
Copy code
public suspend fun <T> awaitAll(
    vararg deferreds: Deferred<T>
): List<T>
j
It returns the same type as the type parameter T.
e
T
must be a single type. Kotlin tries to infer the narrowest type (least upper bound) it can: https://kotlinlang.org/spec/type-inference.html#local-type-inference https://kotlinlang.org/spec/kotlin-type-constraints.html#finding-optimal-constraint-system-solution which leads to this intersection type
even without reading the specification directly, you can see that •
String
and
Boolean
are both
Serializable
(on JVM) •
String
is
Comparable<String>
and
Boolean
is
Comparable<Boolean>
, so they are both
Comparable<Boolean & String>
◦ e.g. comparable to something which is simultaneously both a boolean and a string at the same time. no such value exists, but that doesn't matter for typechecking • those are all of the common supertypes of
String
and
Boolean
(other than `Any`/`Object`) • so the least upper bound is
T = Comparable<Boolean & String> & Serializable
you can't actually write that type in code, https://youtrack.jetbrains.com/issue/KT-13108/Denotable-union-and-intersection-types but the compiler can infer it just fine