can lead to breaking structured concurrency and introduce a whole set of bugs.
The solution to this seems to be to not declare a function that takes a CoroutineScope as suspend, whatever requires suspending could be done in the coroutine scope instead.
For that use case, make the function suspend and wrap the entire function body with:
suspend fun myFunction() = coroutineScope {
val d1 = async { /* */ } // async needs CoroutineScope
val d2 = async { /* */ }
d1.await()
d2.await()
}
Note, this method will create a child scope that inherits all the properties of the scope that called myFunction(). Also the function would not return until both d1 and d2 have finished, regardless if you await/join them!
CoroutineScope is specifically for introducing concurrency.
Every suspend method really should finish all its work before it returns.
Methods that don’t finish can take a CoroutineScope receiver or parameter to hook it into structured concurrency and return a Job/Deferred as a handle to that concurrent work.