Do not transform state-machine when inlining

Sometimes, state-machine, generated in inline functions with
crossinline parameter, is transformed, since all usages should be
renamed.
However, this is wrong: in this case, we will have state-machine
inside state-machine.
This fix addresses the issue.

 #KT-25893 Fixed
This commit is contained in:
Ilmir Usmanov
2018-10-09 22:42:28 +03:00
parent d3908aeb2e
commit 0934db8fbd
9 changed files with 317 additions and 142 deletions
@@ -0,0 +1,32 @@
// WITH_RUNTIME
// LANGUAGE_VERSION: 1.2
// IGNORE_BACKEND: JVM
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
interface SuspendRunnable {
suspend fun run(): String
}
inline fun inlineMe(crossinline c: suspend () -> String) = object : SuspendRunnable {
override suspend fun run() = c()
}
fun box(): String {
var res = "FAIL"
builder {
res = inlineMe { "OK" }.run()
}
return res
}
// Test for continuation of 'run' transformation.
// Since continuation is not suspend lambda, it should not have state-machine.
// @CrossinlineSuspendContinuation_1_2Kt$box$1$doResume$$inlined$inlineMe$1$1.class:
// 0 TABLESWITCH
@@ -0,0 +1,31 @@
// WITH_RUNTIME
// LANGUAGE_VERSION: 1.3
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
interface SuspendRunnable {
suspend fun run(): String
}
inline fun inlineMe(crossinline c: suspend () -> String) = object : SuspendRunnable {
override suspend fun run() = c()
}
fun box(): String {
var res = "FAIL"
builder {
res = inlineMe { "OK" }.run()
}
return res
}
// Test for continuation of 'run' transformation.
// Since continuation is not suspend lambda, it should not have state-machine
// @CrossinlineSuspendContinuation_1_3Kt$box$1$invokeSuspend$$inlined$inlineMe$1$1.class:
// 0 TABLESWITCH
@@ -0,0 +1,13 @@
class Handler(val func: suspend (Any) -> Unit)
inline fun createHandler(crossinline handler: suspend (Any) -> Unit): Handler {
return Handler({ handler.invoke(it) })
}
fun main(args: Array<String>) {
createHandler({
if (it !is String) {}
})
}
// 2 TABLESWITCH
@@ -0,0 +1,23 @@
fun <T> builder(c: suspend () -> T): T = TODO()
class Test {
fun doWork() {
builder {
execute {
getData { getSomeString() }
}
}
}
private inline fun execute(crossinline action: suspend () -> Unit) {
builder { action() }
}
private suspend fun <T> getData(dataProvider: suspend () -> T): T = builder { dataProvider() }
private suspend fun getSomeString(): String {
return "OK"
}
}
// 4 TABLESWITCH