diff --git a/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/intrinsics/IntrinsicsJvm.kt b/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/intrinsics/IntrinsicsJvm.kt index 07e8cee164e..7809c05ede4 100644 --- a/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/intrinsics/IntrinsicsJvm.kt +++ b/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/intrinsics/IntrinsicsJvm.kt @@ -12,8 +12,6 @@ package kotlin.coroutines.intrinsics import kotlin.coroutines.* import kotlin.coroutines.jvm.internal.ContinuationImpl import kotlin.coroutines.jvm.internal.RestrictedContinuationImpl -import kotlin.coroutines.jvm.internal.SuspendFunction0 -import kotlin.coroutines.jvm.internal.SuspendFunction1 import kotlin.internal.InlineOnly /** @@ -111,7 +109,7 @@ public actual fun (suspend R.() -> T).createCoroutineUnchecked( public actual fun (suspend () -> T).createCoroutineUnintercepted( completion: Continuation ): Continuation = - if (this is SuspendFunction0) + if (this is RestrictedContinuationImpl) create(completion) else createCoroutineFromSuspendFunction(completion) { @@ -139,7 +137,7 @@ public actual fun (suspend R.() -> T).createCoroutineUnintercepted( receiver: R, completion: Continuation ): Continuation = - if (this is SuspendFunction1) + if (this is RestrictedContinuationImpl) create(receiver, completion) else { createCoroutineFromSuspendFunction(completion) { diff --git a/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/jvm/internal/ContinuationImpl.kt b/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/jvm/internal/ContinuationImpl.kt index b0ff4dbb278..1c994caef02 100644 --- a/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/jvm/internal/ContinuationImpl.kt +++ b/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/jvm/internal/ContinuationImpl.kt @@ -17,20 +17,40 @@ internal abstract class RestrictedContinuationImpl protected constructor( @JvmField protected val completion: Continuation? ) : Continuation, Serializable { + init { + @Suppress("LeakingThis") + validateContext() + } + + protected open fun validateContext() { + completion?.let { + require(it.context === EmptyCoroutineContext) { "Coroutines with restricted suspension must have EmptyCoroutineContext" } + } + } + public override val context: CoroutineContext get() = EmptyCoroutineContext public override fun resumeWith(result: SuccessOrFailure) { + val completion = completion!! // fail fast when trying to resume continuation without completion try { val outcome = invokeSuspend(result) if (outcome === CoroutineSingletons.COROUTINE_SUSPENDED) return - completion!!.resume(outcome) + completion.resume(outcome) } catch (exception: Throwable) { - completion!!.resumeWithException(exception) + completion.resumeWithException(exception) } } protected abstract fun invokeSuspend(result: SuccessOrFailure): 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") + } } @SinceKotlin("1.3") @@ -41,6 +61,10 @@ internal abstract class ContinuationImpl protected constructor( ) : RestrictedContinuationImpl(completion) { protected constructor(completion: Continuation?) : this(completion, completion?.context) + override fun validateContext() { + // nothing to do here -- supports any context + } + override val context: CoroutineContext get() = _context!! @@ -53,14 +77,15 @@ internal abstract class ContinuationImpl protected constructor( .also { intercepted = this } public override fun resumeWith(result: SuccessOrFailure) { + val completion = completion!! // fail fast when trying to resume continuation without completion try { val outcome = invokeSuspend(result) if (outcome === CoroutineSingletons.COROUTINE_SUSPENDED) return disposeIntercepted() - completion!!.resume(outcome) + completion.resume(outcome) } catch (exception: Throwable) { disposeIntercepted() - completion!!.resumeWithException(exception) + completion.resumeWithException(exception) } } @@ -71,6 +96,11 @@ internal abstract class ContinuationImpl protected constructor( } this.intercepted = CompletedContinuation // just in case } + + override fun toString(): String { + // todo: how continuation shall be rendered? + return "Continuation @ ${this::class.java.name}" + } } // todo: Do we really need it? @@ -80,7 +110,7 @@ internal object CompletedContinuation : Continuation { override fun resumeWith(result: SuccessOrFailure) { error("This continuation is already complete") - } + } } internal abstract class RestrictedSuspendLambda protected constructor( @@ -91,7 +121,11 @@ internal abstract class RestrictedSuspendLambda protected constructor( public override fun getArity(): Int = arity - public override fun toString(): String = Reflection.renderLambdaToString(this) + public override fun toString(): String = + if (completion == null) + Reflection.renderLambdaToString(this) // this is lambda + else + super.toString() // this is continuation } internal abstract class SuspendLambda protected constructor( @@ -102,16 +136,9 @@ internal abstract class SuspendLambda protected constructor( public override fun getArity(): Int = arity - public override fun toString(): String = Reflection.renderLambdaToString(this) -} - -@SinceKotlin("1.3") -internal interface SuspendFunction0 : Function1, Any?> { - fun create(completion: Continuation<*>): Continuation -} - -@SinceKotlin("1.3") -internal interface SuspendFunction1 : Function2, Any?> { - fun create(receiver: Any?, completion: Continuation<*>): Continuation -} - + public override fun toString(): String = + if (completion == null) + Reflection.renderLambdaToString(this) // this is lambda + else + super.toString() // this is continuation +} \ No newline at end of file