A suspend function can be called from another suspend context and still return an ordinary value.

suspend function A suspend function marks work that can cooperate with a coroutine context, even when this tiny example completes immediately.

Suspend Function Shape

id
SuspendFunctionShape.kt
Replay: real traced execution (multi-file project)
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine

suspend fun loadLabel(id: Int): String {
    val normalized = id.coerceAtLeast(0)
    return "item-$normalized"
}

fun main() {
    val id = 2
    var output = "pending"

    val job: suspend () -> String = {
        loadLabel(id)
    }

    job.startCoroutine(object : Continuation<String> {
        override val context = EmptyCoroutineContext

        override fun resumeWith(result: Result<String>) {
            output = result.getOrThrow()
        }
    })

    println("result=$output")
}
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine

suspend fun loadLabel(id: Int): String {
    val normalized = id.coerceAtLeast(0)
    return "item-$normalized"
}

fun main() {
    val id = 0
    var output = "pending"

    val job: suspend () -> String = {
        loadLabel(id)
    }

    job.startCoroutine(object : Continuation<String> {
        override val context = EmptyCoroutineContext

        override fun resumeWith(result: Result<String>) {
            output = result.getOrThrow()
        }
    })

    println("result=$output")
}
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine

suspend fun loadLabel(id: Int): String {
    val normalized = id.coerceAtLeast(0)
    return "item-$normalized"
}

fun main() {
    val id = 5
    var output = "pending"

    val job: suspend () -> String = {
        loadLabel(id)
    }

    job.startCoroutine(object : Continuation<String> {
        override val context = EmptyCoroutineContext

        override fun resumeWith(result: Result<String>) {
            output = result.getOrThrow()
        }
    })

    println("result=$output")
}
  1. id ← 2, output ← pending, job ← () -> kotlin.String

    10fun main() {11    val id→ 2 = 2 //@id=0, 512    var output→ pending = "pending"1314    val job→ () -> kotlin.String: suspend () -> String = {15        loadLabel(id)16    }1718    job() -> kotlin.String.startCoroutine(object : Continuation<String> {19        override val context = EmptyCoroutineContext2021        override fun resumeWith(result: Result<String>) {22            output = result.getOrThrow()23        }24    })
  2. normalized ← 2

    5suspend fun loadLabel(id2: Int): String {6    val normalized→ 2 = id2.coerceAtLeast(0)7    return "item-$normalized2"8}
  3. override fun resumeWith(result: Result<String>)

    18job() -> kotlin.String.startCoroutine(object : Continuation<String> {19    override val context = EmptyCoroutineContext2021    override fun resumeWith(resultSuccess(item-2): Result<String>) {22        output = resultSuccess(item-2).getOrThrow()23    }24})
  4. println("result=$output")

    26    println("result=$outputitem-2")27}
    outputresult=item-2
  1. id ← 0, output ← pending, job ← () -> kotlin.String

    10fun main() {11    val id→ 0 = 012    var output→ pending = "pending"1314    val job→ () -> kotlin.String: suspend () -> String = {15        loadLabel(id)16    }1718    job() -> kotlin.String.startCoroutine(object : Continuation<String> {19        override val context = EmptyCoroutineContext2021        override fun resumeWith(result: Result<String>) {22            output = result.getOrThrow()23        }24    })
  2. normalized ← 0

    5suspend fun loadLabel(id0: Int): String {6    val normalized→ 0 = id0.coerceAtLeast(0)7    return "item-$normalized0"8}
  3. override fun resumeWith(result: Result<String>)

    18job() -> kotlin.String.startCoroutine(object : Continuation<String> {19    override val context = EmptyCoroutineContext2021    override fun resumeWith(resultSuccess(item-0): Result<String>) {22        output = resultSuccess(item-0).getOrThrow()23    }24})
  4. println("result=$output")

    26    println("result=$outputitem-0")27}
    outputresult=item-0
  1. id ← 5, output ← pending, job ← () -> kotlin.String

    10fun main() {11    val id→ 5 = 512    var output→ pending = "pending"1314    val job→ () -> kotlin.String: suspend () -> String = {15        loadLabel(id)16    }1718    job() -> kotlin.String.startCoroutine(object : Continuation<String> {19        override val context = EmptyCoroutineContext2021        override fun resumeWith(result: Result<String>) {22            output = result.getOrThrow()23        }24    })
  2. normalized ← 5

    5suspend fun loadLabel(id5: Int): String {6    val normalized→ 5 = id5.coerceAtLeast(0)7    return "item-$normalized5"8}
  3. override fun resumeWith(result: Result<String>)

    18job() -> kotlin.String.startCoroutine(object : Continuation<String> {19    override val context = EmptyCoroutineContext2021    override fun resumeWith(resultSuccess(item-5): Result<String>) {22        output = resultSuccess(item-5).getOrThrow()23    }24})
  4. println("result=$output")

    26    println("result=$outputitem-5")27}
    outputresult=item-5