Consider a code like this:
interface T
object BadT : T
class GoodT : T
fun CoroutineScope.doStuff(flag: Boolean): Deferred<T> {
if (!flag) return CompletableDeferred(BadT)
return async { computeGoodT() }
}
after some thinking I decided to drop BadT and use nullability instead, so I naturally changed the code to
interface T
class GoodT : T
fun CoroutineScope.doStuff(flag: Boolean): Deferred<T?> {
if (!flag) return CompletableDeferred(null)
return async { computeGoodT() }
}
And was puzzled to see my tests stuck. During an investigation I noticed that after my change the CompletableDeferred started to resolve to public fun <T> CompletableDeferred(parent: Job? = null) instead of public fun <T> CompletableDeferred(value: T). I believe this misuse might occasionally happen, so an inspection would be nice