Support inline suspend functions built with compiler version less than 1.1.4/1.2-M1

The error message is removed and is replaced with a code that adapts
inline suspend functions produced by the old compiler with the
suspension markers that new compiler expects.
This commit is contained in:
Roman Elizarov
2017-07-13 22:53:30 +03:00
parent 9f0810f723
commit f2b5f37b22
14 changed files with 200 additions and 66 deletions
@@ -1,4 +0,0 @@
package library
inline suspend fun foo() {}
suspend fun bar() {}
@@ -1,6 +0,0 @@
import library.*
suspend fun test() {
foo()
bar()
}
@@ -1,4 +0,0 @@
compiler/testData/bytecodeVersion/obsoleteInlineSuspend/B.kt:4:5: error: cannot inline suspend function built with compiler version less than 1.1.4/1.2-M1
foo()
^
COMPILATION_ERROR
@@ -0,0 +1,31 @@
package library
import kotlin.coroutines.experimental.*
var continuation: Continuation<Unit>? = null
val sb = java.lang.StringBuilder()
fun append(s: String) { sb.append(s) }
val libraryResult: String get() = sb.toString()
// this is an inline tail-suspend function that should work properly despite being compiler by
// compiler before 1.1.4 version that did not include suspension marks into bytecode.
// In order to test that it works properly it shall actually suspend during its execution
inline suspend fun foo(block: () -> Unit) {
append("(foo)")
block()
return suspendCoroutine<Unit> { continuation = it }
}
suspend fun bar() {
append("(bar)")
return suspendCoroutine<Unit> { continuation = it }
}
fun resumeLibrary() {
continuation?.let {
continuation = null
it.resume(Unit)
}
}
@@ -0,0 +1,36 @@
import library.*
import kotlin.coroutines.experimental.*
suspend fun test() {
append("[foo]")
foo { // we are inlining foo here
append("(block)")
}
append("[bar]")
bar() // and invoking suspending function bar
append("[test]")
}
fun runBlockingLibrary(block: suspend () -> Unit): String {
var done = false
block.startCoroutine(object : Continuation<Unit> {
override val context: CoroutineContext = EmptyCoroutineContext
override fun resume(value: Unit) { done = true }
override fun resumeWithException(exception: Throwable) { throw exception }
})
var resumeCounter = 0
while (!done) {
resumeCounter++
resumeLibrary()
}
return "$libraryResult:resumes=$resumeCounter"
}
// Retruns array of expected and received string
fun run(): Array<String> {
val result = runBlockingLibrary {
test()
}
return arrayOf("[foo](foo)(block)[bar](bar)[test]:resumes=2", result)
}