Problem with inline functions with coroutines and exposed



The following code does not compile. It is based on the pipeline example. The problem is in the produceNumbers function. The send call of the producer is embedded in a lambda. This works if the lambda is inline. (see someInlineLamda). The transaction call is not inline and gives a compile error (Error:(24, 13) Kotlin: Suspension functions can be called only within coroutine body).

If I move the transaction code to another inline lambda (see someInlineTransactionLambda) the lambda needs to be crossinline due to non-local returns but the error remains.

Any ideas on how to resolve this?

import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.channels.*

inline fun <E> someInlineLambda(x: Int, function: (Int) -> E): Unit {
    for (i in 0..1) 

inline fun <E> someInlineTransactionLambda(x: Int, crossinline function: (Int) -> E): Unit {
    transaction {
        for (i in 0..1) {

fun produceNumbers() = produce<Int>(CommonPool) {
    var x = 1
    while (true) {
        someInlineLambda(x) {
            send(x++)     // OK - inline lambda
        transaction {    // start transaction in exposed land
            send(x++)    // Error:(24, 13) Kotlin: Suspension functions can be called only within coroutine body
        someInlineTransactionLamda {    // start transaction in exposed land, wrapped in inline lambda
            send(x++)    // did not work :(

fun square(numbers: ReceiveChannel<Int>) = produce<Int>(CommonPool) {
    for (x in numbers) send(x * x)

fun main(args: Array<String>) = runBlocking<Unit> {
    val numbers = produceNumbers() // produces integers from 1 and on
    val squares = square(numbers) // squares integers
    for (i in 1..5) println(squares.receive()) // print first five
    println("Done!") // we are done
    squares.cancel() // need to cancel these coroutines in a larger app


To make non-inline function work with suspensions you’ll have to explicitly mark the functions and their lambda arguments with suspend keyword.


Ok got it. Thanks.