From c0ef1311baac0f61b16615bb408ddc8f1bbc69b5 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Fri, 14 Sep 2018 19:30:34 +0300 Subject: [PATCH] [JS IR BE] Fix runtime for Release coroutines --- .../kotlin/js/test/BasicIrBoxTest.kt | 33 ++-- .../js/irRuntime/coroutineInternalJS.kt | 37 +++++ .../coroutines_12/coroutineAliases.kt | 9 ++ .../coroutineIntrinsics.kt | 22 +-- .../{ => coroutines_12}/coroutines.kt | 8 + .../{ => coroutines_12}/coroutinesInternal.kt | 31 +--- .../irRuntime/coroutines_13/CoroutineImpl.kt | 102 ++++++++++++ .../irRuntime/coroutines_13/IntrinsicsJs.kt | 148 ++++++++++++++++++ .../coroutines_13/coroutineAliases.kt | 9 ++ libraries/stdlib/js/irRuntime/exceptions.kt | 2 + libraries/stdlib/js/irRuntime/hacks.kt | 14 -- 11 files changed, 350 insertions(+), 65 deletions(-) create mode 100644 libraries/stdlib/js/irRuntime/coroutineInternalJS.kt create mode 100644 libraries/stdlib/js/irRuntime/coroutines_12/coroutineAliases.kt rename libraries/stdlib/js/irRuntime/{ => coroutines_12}/coroutineIntrinsics.kt (93%) rename libraries/stdlib/js/irRuntime/{ => coroutines_12}/coroutines.kt (98%) rename libraries/stdlib/js/irRuntime/{ => coroutines_12}/coroutinesInternal.kt (60%) create mode 100644 libraries/stdlib/js/irRuntime/coroutines_13/CoroutineImpl.kt create mode 100644 libraries/stdlib/js/irRuntime/coroutines_13/IntrinsicsJs.kt create mode 100644 libraries/stdlib/js/irRuntime/coroutines_13/coroutineAliases.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt index af14d929c5b..1427466e70b 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt @@ -15,16 +15,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.test.TargetBackend import java.io.File -private val runtimeSources = listOfKtFilesFrom( - // TODO: share more coroutine code between JS BEs - // TODO: don't generate code for external declarations, until that: - // it's important now than *H.kt files at the start since we generate code for them - // and actual versions just will override them later. - "libraries/stdlib/coroutines-experimental/src/kotlin/coroutines/experimental/CoroutinesExperimentalH.kt", - "libraries/stdlib/coroutines-experimental/src/kotlin/coroutines/experimental/CoroutinesIntrinsicsExperimentalH.kt", - "libraries/stdlib/coroutines-experimental/src/kotlin/coroutines/experimental/SequenceBuilder.kt", - "libraries/stdlib/coroutines-experimental/src/kotlin/coroutines/experimental/Coroutines.kt", - +private val runtimeSourcesCommon = listOfKtFilesFrom( "core/builtins/src/kotlin", "libraries/stdlib/common/src", "libraries/stdlib/src/kotlin/", @@ -80,9 +71,27 @@ private val runtimeSources = listOfKtFilesFrom( "libraries/stdlib/js/irRuntime/rangeExtensions.kt" ) + +private val coroutine12Files = listOfKtFilesFrom( + "libraries/stdlib/js/irRuntime/coroutines_12" +) + +private val coroutine13Files = listOfKtFilesFrom( + "libraries/stdlib/coroutines/common", + "libraries/stdlib/coroutines/js/src/kotlin/coroutines/SafeContinuationJs.kt", + "libraries/stdlib/coroutines/src", + // TODO: merge coroutines_13 with JS BE coroutines + "libraries/stdlib/js/irRuntime/coroutines_13" +) + private var runtimeResult: Result? = null private val runtimeFile = File("js/js.translator/testData/out/irBox/testRuntime.js") +private val runtimeSources_12 = (runtimeSourcesCommon - coroutine13Files + coroutine12Files).distinct() +private val runtimeSources_13 = (runtimeSourcesCommon - coroutine12Files + coroutine13Files).distinct() + +private val runtimeSources = runtimeSources_13 + abstract class BasicIrBoxTest( pathToTestDir: String, testGroupOutputDirPrefix: String, @@ -128,11 +137,11 @@ abstract class BasicIrBoxTest( LanguageFeature.MultiPlatformProjects to LanguageFeature.State.ENABLED ), analysisFlags = mapOf( - AnalysisFlag.useExperimental to listOf("kotlin.contracts.ExperimentalContracts", "kotlin.Experimental") + AnalysisFlag.useExperimental to listOf("kotlin.contracts.ExperimentalContracts", "kotlin.Experimental"), + AnalysisFlag.allowResultReturnType to true ) ) - if (runtimeResult == null) { runtimeResult = compile(config.project, runtimeSources.map(::createPsiFile), runtimeConfiguration) runtimeFile.write(runtimeResult!!.generatedCode) diff --git a/libraries/stdlib/js/irRuntime/coroutineInternalJS.kt b/libraries/stdlib/js/irRuntime/coroutineInternalJS.kt new file mode 100644 index 00000000000..c1e06e8add1 --- /dev/null +++ b/libraries/stdlib/js/irRuntime/coroutineInternalJS.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + + +package kotlin.js + +import kotlin.js.coroutineAliases.* + + +@PublishedApi +internal fun getContinuation(): ContinuationAlias { throw Exception("Implemented as intrinsic") } +// Do we really need this intrinsic in JS? + +@PublishedApi +internal suspend fun returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T { + throw Exception("Implemented as intrinsic") +} + +@PublishedApi +internal fun interceptContinuationIfNeeded( + context: CoroutineContextAlias, + continuation: ContinuationAlias +) = context[ContinuationInterceptorAlias]?.interceptContinuation(continuation) ?: continuation + + +@SinceKotlin("1.2") +@PublishedApi +internal suspend fun getCoroutineContext(): CoroutineContextAlias = getContinuation().context + +// TODO: remove `JS` suffix oncec `NameGenerator` is implemented +@PublishedApi +internal suspend fun suspendCoroutineUninterceptedOrReturnJS(block: (ContinuationAlias) -> Any?): T = + returnIfSuspended(block(getContinuation())) + + diff --git a/libraries/stdlib/js/irRuntime/coroutines_12/coroutineAliases.kt b/libraries/stdlib/js/irRuntime/coroutines_12/coroutineAliases.kt new file mode 100644 index 00000000000..030d3b703e8 --- /dev/null +++ b/libraries/stdlib/js/irRuntime/coroutines_12/coroutineAliases.kt @@ -0,0 +1,9 @@ + +package kotlin.js.coroutineAliases + +import kotlin.coroutines.experimental.* + + +typealias ContinuationAlias = Continuation +typealias CoroutineContextAlias = CoroutineContext +typealias ContinuationInterceptorAlias = ContinuationInterceptor \ No newline at end of file diff --git a/libraries/stdlib/js/irRuntime/coroutineIntrinsics.kt b/libraries/stdlib/js/irRuntime/coroutines_12/coroutineIntrinsics.kt similarity index 93% rename from libraries/stdlib/js/irRuntime/coroutineIntrinsics.kt rename to libraries/stdlib/js/irRuntime/coroutines_12/coroutineIntrinsics.kt index df09bfd79ff..712dcab9a55 100644 --- a/libraries/stdlib/js/irRuntime/coroutineIntrinsics.kt +++ b/libraries/stdlib/js/irRuntime/coroutines_12/coroutineIntrinsics.kt @@ -7,11 +7,9 @@ package kotlin.coroutines.experimental.intrinsics import kotlin.coroutines.experimental.* -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -@Suppress("UNUSED_PARAMETER") -public suspend inline fun suspendCoroutineOrReturn(crossinline block: (Continuation) -> Any?): T = - suspendCoroutineUninterceptedOrReturn { cont -> block(cont.intercepted()) } +@PublishedApi +internal fun normalizeContinuation(continuation: Continuation): Continuation = + (continuation as? CoroutineImpl)?.facade ?: continuation /** * Obtains the current continuation instance inside suspend functions and either suspends @@ -19,9 +17,16 @@ public suspend inline fun suspendCoroutineOrReturn(crossinline block: (Conti * * Unlike [suspendCoroutineOrReturn] it does not intercept continuation. */ + +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +@Suppress("UNUSED_PARAMETER") +public suspend inline fun suspendCoroutineOrReturn(crossinline block: (Continuation) -> Any?): T = + suspendCoroutineUninterceptedOrReturn { cont -> block(cont.intercepted()) } + @SinceKotlin("1.2") public suspend fun suspendCoroutineUninterceptedOrReturn(block: (Continuation) -> Any?): T = - returnIfSuspended(block(getContinuation())) + throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic") /** * Intercept continuation with [ContinuationInterceptor]. @@ -30,14 +35,9 @@ public suspend fun suspendCoroutineUninterceptedOrReturn(block: (Continuatio @kotlin.internal.InlineOnly public inline fun Continuation.intercepted() = normalizeContinuation(this) -/** - * This value is used as a return value of [suspendCoroutineOrReturn] `block` argument to state that - * the execution was suspended and will not return any result immediately. - */ @SinceKotlin("1.1") public val COROUTINE_SUSPENDED: Any = Any() - @SinceKotlin("1.1") @Suppress("UNCHECKED_CAST") @kotlin.internal.InlineOnly diff --git a/libraries/stdlib/js/irRuntime/coroutines.kt b/libraries/stdlib/js/irRuntime/coroutines_12/coroutines.kt similarity index 98% rename from libraries/stdlib/js/irRuntime/coroutines.kt rename to libraries/stdlib/js/irRuntime/coroutines_12/coroutines.kt index ede34768513..d57a46ed869 100644 --- a/libraries/stdlib/js/irRuntime/coroutines.kt +++ b/libraries/stdlib/js/irRuntime/coroutines_12/coroutines.kt @@ -291,6 +291,14 @@ private val RESUMED: Any? = Any() private class Fail(val exception: Throwable) +@SinceKotlin("1.2") +@Suppress("WRONG_MODIFIER_TARGET") +@kotlin.internal.InlineOnly +public suspend inline val coroutineContext: CoroutineContext + get() { + throw NotImplementedError("Implemented as intrinsic") + } + @kotlin.internal.InlineOnly internal inline fun processBareContinuationResume(completion: Continuation<*>, block: () -> Any?) { try { diff --git a/libraries/stdlib/js/irRuntime/coroutinesInternal.kt b/libraries/stdlib/js/irRuntime/coroutines_12/coroutinesInternal.kt similarity index 60% rename from libraries/stdlib/js/irRuntime/coroutinesInternal.kt rename to libraries/stdlib/js/irRuntime/coroutines_12/coroutinesInternal.kt index 58744328f74..71ffe2e0463 100644 --- a/libraries/stdlib/js/irRuntime/coroutinesInternal.kt +++ b/libraries/stdlib/js/irRuntime/coroutines_12/coroutinesInternal.kt @@ -3,36 +3,11 @@ * that can be found in the license/LICENSE.txt file. */ -package kotlin.js - -import kotlin.coroutines.experimental.* - -internal fun getContinuation(): Continuation { throw Exception("Implemented as intrinsic") } -// Do we really need this intrinsic in JS? -internal suspend fun returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T { - throw Exception("Implemented as intrinsic") -} - -fun normalizeContinuation(continuation: Continuation): Continuation = - (continuation as? CoroutineImpl)?.facade ?: continuation - -internal fun interceptContinuationIfNeeded( - context: CoroutineContext, - continuation: Continuation -) = context[ContinuationInterceptor]?.interceptContinuation(continuation) ?: continuation - - -@SinceKotlin("1.2") -@Suppress("WRONG_MODIFIER_TARGET") -public suspend val coroutineContext: CoroutineContext - get() { - throw Exception("Implemented as intrinsic") - } - +package kotlin.coroutines.experimental internal abstract class CoroutineImpl(private val completion: Continuation) : Continuation { protected var exceptionState = 0 - protected var label: Int = 0 + protected var state: Int = 0 protected var exception: dynamic = null protected var result: dynamic = null @@ -51,7 +26,7 @@ internal abstract class CoroutineImpl(private val completion: Continuation override fun resumeWithException(exception: Throwable) { // TODO: once we have arrays working refact it with exception table - this.label = exceptionState + this.state = exceptionState this.exception = exception doResumeWrapper() } diff --git a/libraries/stdlib/js/irRuntime/coroutines_13/CoroutineImpl.kt b/libraries/stdlib/js/irRuntime/coroutines_13/CoroutineImpl.kt new file mode 100644 index 00000000000..e4c3ba48ca9 --- /dev/null +++ b/libraries/stdlib/js/irRuntime/coroutines_13/CoroutineImpl.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package kotlin.coroutines + +import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED + +@SinceKotlin("1.3") +@JsName("CoroutineImpl") +internal abstract class CoroutineImpl(private val resultContinuation: Continuation?) : Continuation { + protected var state = 0 + protected var exceptionState = 0 + protected var result: dynamic = null + protected var exception: dynamic = null + protected var finallyPath: Array? = null + + public override val context: CoroutineContext get() = resultContinuation!!.context + + private var intercepted_: Continuation? = null + + public fun intercepted(): Continuation = + intercepted_ + ?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this) + .also { intercepted_ = it } + + override fun resumeWith(result: Result) { + var current = this + var currentResult: Any? = result.getOrNull() + var currentException: Throwable? = result.exceptionOrNull() + + // This loop unrolls recursion in current.resumeWith(param) to make saner and shorter stack traces on resume + while (true) { + with(current) { + // Set result and exception fields in the current continuation + if (currentException == null) { + this.result = currentResult + } else { + state = exceptionState + exception = currentException + } + + try { + val outcome = doResume() + if (outcome === COROUTINE_SUSPENDED) return + currentResult = outcome + currentException = null + } catch (exception: dynamic) { // Catch all exceptions + currentResult = null + currentException = exception.unsafeCast() + } + + releaseIntercepted() // this state machine instance is terminating + + val completion = resultContinuation!! + + if (completion is CoroutineImpl) { + // unrolling recursion via loop + current = completion + } else { + // top-level completion reached -- invoke and return + if (currentException != null) { + completion.resumeWithException(currentException!!) + } else { + completion.resume(currentResult) + } + return + } + } + } + } + + private fun releaseIntercepted() { + val intercepted = intercepted_ + if (intercepted != null && intercepted !== this) { + context[ContinuationInterceptor]!!.releaseInterceptedContinuation(intercepted) + } + this.intercepted_ = CompletedContinuation // just in case + } + + protected abstract fun doResume(): Any? + + public open fun create(completion: Continuation<*>): Continuation { + throw UnsupportedOperationException("create(Continuation) has not been overridden") + } + + public open fun create(value: Any?, completion: Continuation<*>): Continuation { + throw UnsupportedOperationException("create(Any?;Continuation) has not been overridden") + } +} + +internal object CompletedContinuation : Continuation { + override val context: CoroutineContext + get() = error("This continuation is already complete") + + override fun resumeWith(result: Result) { + error("This continuation is already complete") + } + + override fun toString(): String = "This continuation is already complete" +} diff --git a/libraries/stdlib/js/irRuntime/coroutines_13/IntrinsicsJs.kt b/libraries/stdlib/js/irRuntime/coroutines_13/IntrinsicsJs.kt new file mode 100644 index 00000000000..0ca60f6a183 --- /dev/null +++ b/libraries/stdlib/js/irRuntime/coroutines_13/IntrinsicsJs.kt @@ -0,0 +1,148 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "UNCHECKED_CAST") + +package kotlin.coroutines.intrinsics + +import kotlin.coroutines.* +import kotlin.internal.InlineOnly + +/** + * Starts unintercepted coroutine without receiver and with result type [T] and executes it until its first suspension. + * Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends. + * In the later case, the [completion] continuation is invoked when coroutine completes with result or exception. + * + * The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might + * be present in the completion's [CoroutineContext]. It is invoker's responsibility to ensure that the proper invocation + * context is established. + * + * This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of suspended + * coroutine using a reference to the suspending function. + */ +@SinceKotlin("1.3") +@InlineOnly +public actual inline fun (suspend () -> T).startCoroutineUninterceptedOrReturn( + completion: Continuation +): Any? { + val a = this.asDynamic() + return if (jsTypeOf(a) == "function") a(completion, false) + else a.invoke(completion) +} + +/** + * Starts unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension. + * Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends. + * In the later case, the [completion] continuation is invoked when coroutine completes with result or exception. + * + * The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might + * be present in the completion's [CoroutineContext]. It is invoker's responsibility to ensure that the proper invocation + * context is established. + * + * This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of suspended + * coroutine using a reference to the suspending function. + */ +@SinceKotlin("1.3") +@InlineOnly +public actual inline fun (suspend R.() -> T).startCoroutineUninterceptedOrReturn( + receiver: R, + completion: Continuation +): Any? { + val a = this.asDynamic() + return if(jsTypeOf(a) == "function") a(receiver, completion, false) + else a.invoke_P1(receiver, completion) +} + + +/** + * Creates unintercepted coroutine without receiver and with result type [T]. + * This function creates a new, fresh instance of suspendable computation every time it is invoked. + * + * To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance. + * The [completion] continuation is invoked when coroutine completes with result or exception. + * + * This function returns unintercepted continuation. + * Invocation of `resume(Unit)` starts coroutine directly in the invoker's thread without going through the + * [ContinuationInterceptor] that might be present in the completion's [CoroutineContext]. + * It is invoker's responsibility to ensure that the proper invocation context is established. + * [Continuation.intercepted] can be used to acquire the intercepted continuation. + * + * Repeated invocation of any resume function on the resulting continuation corrupts the + * state machine of the coroutine and may result in arbitrary behaviour or exception. + */ +@SinceKotlin("1.3") +public actual fun (suspend () -> T).createCoroutineUnintercepted( + completion: Continuation +): Continuation = + // Kotlin/JS suspend lambdas have an extra parameter `suspended` + if (this.asDynamic().length == 2) { + // When `suspended` is true the continuation is created, but not executed + this.asDynamic()(completion, true) + } else { + createCoroutineFromSuspendFunction(completion) { + val a = this.asDynamic() + if (jsTypeOf(a) == "function") { + a(completion) + } else { + a.invoke(completion) + } + } + } + +/** + * Creates unintercepted coroutine with receiver type [R] and result type [T]. + * This function creates a new, fresh instance of suspendable computation every time it is invoked. + * + * To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance. + * The [completion] continuation is invoked when coroutine completes with result or exception. + * + * This function returns unintercepted continuation. + * Invocation of `resume(Unit)` starts coroutine directly in the invoker's thread without going through the + * [ContinuationInterceptor] that might be present in the completion's [CoroutineContext]. + * It is invoker's responsibility to ensure that the proper invocation context is established. + * [Continuation.intercepted] can be used to acquire the intercepted continuation. + * + * Repeated invocation of any resume function on the resulting continuation corrupts the + * state machine of the coroutine and may result in arbitrary behaviour or exception. + */ +@SinceKotlin("1.3") +public actual fun (suspend R.() -> T).createCoroutineUnintercepted( + receiver: R, + completion: Continuation +): Continuation = + // Kotlin/JS suspend lambdas have an extra parameter `suspended` + if (this.asDynamic().length == 3) { + // When `suspended` is true the continuation is created, but not executed + this.asDynamic()(receiver, completion, true) + } else { + createCoroutineFromSuspendFunction(completion) { + val a = this.asDynamic() + if (jsTypeOf(a) == "function") { + a(receiver, completion) + } else { + a.invoke_P1(receiver, completion) + } + } + } + +/** + * Intercepts this continuation with [ContinuationInterceptor]. + */ +@SinceKotlin("1.3") +public actual fun Continuation.intercepted(): Continuation = + (this as? CoroutineImpl)?.intercepted() ?: this + + +private inline fun createCoroutineFromSuspendFunction( + completion: Continuation, + crossinline block: () -> Any? +): Continuation { + return object : CoroutineImpl(completion as Continuation) { + override fun doResume(): Any? { + if (exception != null) throw exception + return block() + } + } +} diff --git a/libraries/stdlib/js/irRuntime/coroutines_13/coroutineAliases.kt b/libraries/stdlib/js/irRuntime/coroutines_13/coroutineAliases.kt new file mode 100644 index 00000000000..3312d3b227b --- /dev/null +++ b/libraries/stdlib/js/irRuntime/coroutines_13/coroutineAliases.kt @@ -0,0 +1,9 @@ + +package kotlin.js.coroutineAliases + +import kotlin.coroutines.* + + +typealias ContinuationAlias = Continuation +typealias CoroutineContextAlias = CoroutineContext +typealias ContinuationInterceptorAlias = ContinuationInterceptor \ No newline at end of file diff --git a/libraries/stdlib/js/irRuntime/exceptions.kt b/libraries/stdlib/js/irRuntime/exceptions.kt index b505f2b7966..9fa5eb860cc 100644 --- a/libraries/stdlib/js/irRuntime/exceptions.kt +++ b/libraries/stdlib/js/irRuntime/exceptions.kt @@ -97,3 +97,5 @@ fun THROW_CCE() { fun THROW_NPE() { throw NullPointerException() } + +fun error(s: String): Nothing = throw IllegalStateException(s, null) \ No newline at end of file diff --git a/libraries/stdlib/js/irRuntime/hacks.kt b/libraries/stdlib/js/irRuntime/hacks.kt index b396690f36d..ac45db79a06 100644 --- a/libraries/stdlib/js/irRuntime/hacks.kt +++ b/libraries/stdlib/js/irRuntime/hacks.kt @@ -5,8 +5,6 @@ package kotlin -import kotlin.coroutines.experimental.SequenceBuilder - // TODO: Ignore FunctionN interfaces public interface Function0 : Function { @@ -26,15 +24,3 @@ public interface Function3 : Function { } public inline fun arrayOfNulls(size: Int): Array = js("[]") // FIXME: Implement - -internal inline fun buildSequence(noinline builderAction: suspend SequenceBuilder.() -> Unit): Sequence = - kotlin.coroutines.experimental.buildSequence(builderAction) - -internal inline fun buildIterator(noinline builderAction: suspend SequenceBuilder.() -> Unit): Iterator = - kotlin.coroutines.experimental.buildIterator(builderAction) - -internal inline fun sequence(noinline builderAction: suspend SequenceBuilder.() -> Unit): Sequence = - kotlin.coroutines.experimental.buildSequence(builderAction) - -internal inline fun iterator(noinline builderAction: suspend SequenceBuilder.() -> Unit): Iterator = - kotlin.coroutines.experimental.buildIterator(builderAction)