// WITH_STDLIB
// FULL_JDK
// TARGET_BACKEND: JVM
// API_VERSION: LATEST
// PREFER_IN_TEST_OVER_STDLIB

// FILE: Spilling.kt

package kotlin.coroutines.jvm.internal

@Suppress("UNUSED_PARAMETER", "unused")
internal fun nullOutSpilledVariable(value: Any?): Any? = value

// FILE: test.kt

import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*

fun blackhole(vararg a: Any?) {}

val spilledVariables = mutableSetOf<Pair<String, String>>()

var c: Continuation<Unit>? = null

suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn<Unit> { continuation ->
    spilledVariables.clear()
    for (field in continuation.javaClass.declaredFields) {
        if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue
        field.isAccessible = true
        spilledVariables += field.name to "${field.get(continuation)}"
    }
    c = continuation
    COROUTINE_SUSPENDED
}

val test: suspend (Int) -> Unit = { unused ->
    saveSpilledVariables()
}

fun builder(c: suspend () -> Unit) {
    c.startCoroutine(Continuation(EmptyCoroutineContext) {
        it.getOrThrow()
    })
}

fun box(): String {
    builder {
        test(1)
    }

    if (spilledVariables != setOf("label" to "1")) return "FAIL 1: $spilledVariables"
    c?.resume(Unit)
    if (spilledVariables != setOf("label" to "1")) return "FAIL 2: $spilledVariables"

    return "OK"
}