diff options
author | Ilya Gorbunov <ilya.gorbunov@jetbrains.com> | 2020-07-07 04:50:42 +0300 |
---|---|---|
committer | Ilya Gorbunov <ilya.gorbunov@jetbrains.com> | 2020-07-10 15:47:21 +0300 |
commit | 0a8b4c6996f4b8a4c66c696ec97a3b855754b7cf (patch) | |
tree | e6c7f211950927d97e11b8718af45465e1a9f452 | |
parent | 17e210e19cb0d46b71c0969629ceed8e34ff3d95 (diff) | |
download | kotlin-0a8b4c6996f4b8a4c66c696ec97a3b855754b7cf.tar.gz |
Add EXACTLY_ONCE contract to suspendCoroutine* functions
Update line numbers in the affected test.
(cherry picked from commit 2f3e1dcbc6d97b38cdca2dbbb954ef4adf728668)
4 files changed, 23 insertions, 11 deletions
diff --git a/js/js.translator/testData/lineNumbers/coroutine.kt b/js/js.translator/testData/lineNumbers/coroutine.kt index 41b8a593698..c4562c1c16d 100644 --- a/js/js.translator/testData/lineNumbers/coroutine.kt +++ b/js/js.translator/testData/lineNumbers/coroutine.kt @@ -14,4 +14,4 @@ suspend fun bar(): Unit { println(a + b) } -// LINES: 38 4 4 4 7 5 5 44 44 5 92 44 5 5 6 4 4 4 9 15 9 9 9 * 9 15 10 10 11 11 11 11 11 * 11 12 12 13 13 13 13 13 13 13 14 14 * 9 15 9 9 9 9
\ No newline at end of file +// LINES: 39 4 4 4 7 5 5 45 45 5 92 45 5 5 6 4 4 4 9 15 9 9 9 * 9 15 10 10 11 11 11 11 11 * 11 12 12 13 13 13 13 13 13 13 14 14 * 9 15 9 9 9 9
\ No newline at end of file diff --git a/libraries/stdlib/jvm/test/coroutines/CoroutinesTest.kt b/libraries/stdlib/jvm/test/coroutines/CoroutinesTest.kt index 99b79a4b77f..a4b6b48da42 100644 --- a/libraries/stdlib/jvm/test/coroutines/CoroutinesTest.kt +++ b/libraries/stdlib/jvm/test/coroutines/CoroutinesTest.kt @@ -39,11 +39,17 @@ class DispatcherSwitcher( private val contextDispatcher: TestDispatcher, private val resumeDispatcher: TestDispatcher ) { - suspend fun run(): Int = suspendCoroutine { cont -> - contextDispatcher.assertThread() - resumeDispatcher.executor.execute { - resumeDispatcher.assertThread() - cont.resume(42) + suspend fun run(): Int { + val sideEffect: Int + val runResult = suspendCoroutine<Int> { cont -> + contextDispatcher.assertThread() + resumeDispatcher.executor.execute { + resumeDispatcher.assertThread() + cont.resume(42) + } + sideEffect = 21 } + assertEquals(21, sideEffect) + return runResult } } diff --git a/libraries/stdlib/src/kotlin/coroutines/Continuation.kt b/libraries/stdlib/src/kotlin/coroutines/Continuation.kt index a4f06cf2c6d..375cec539a5 100644 --- a/libraries/stdlib/src/kotlin/coroutines/Continuation.kt +++ b/libraries/stdlib/src/kotlin/coroutines/Continuation.kt @@ -1,10 +1,11 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * 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.contracts.* import kotlin.coroutines.intrinsics.* import kotlin.internal.InlineOnly @@ -138,12 +139,14 @@ public fun <R, T> (suspend R.() -> T).startCoroutine( */ @SinceKotlin("1.3") @InlineOnly -public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T = - suspendCoroutineUninterceptedOrReturn { c: Continuation<T> -> +public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return suspendCoroutineUninterceptedOrReturn { c: Continuation<T> -> val safe = SafeContinuation(c.intercepted()) block(safe) safe.getOrThrow() } +} /** * Returns the context of the current coroutine. diff --git a/libraries/stdlib/src/kotlin/coroutines/intrinsics/Intrinsics.kt b/libraries/stdlib/src/kotlin/coroutines/intrinsics/Intrinsics.kt index ba08334d69a..3b3dd23e4dd 100644 --- a/libraries/stdlib/src/kotlin/coroutines/intrinsics/Intrinsics.kt +++ b/libraries/stdlib/src/kotlin/coroutines/intrinsics/Intrinsics.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -8,6 +8,7 @@ package kotlin.coroutines.intrinsics +import kotlin.contracts.* import kotlin.coroutines.* import kotlin.internal.InlineOnly @@ -37,8 +38,10 @@ import kotlin.internal.InlineOnly @SinceKotlin("1.3") @InlineOnly @Suppress("UNUSED_PARAMETER", "RedundantSuspendModifier") -public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T = +public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic") +} /** * This value is used as a return value of [suspendCoroutineUninterceptedOrReturn] `block` argument to state that |