JVM_IR: keep suspend fun return type in IrCalls
Otherwise:
* should the dispatch receiver of a call be another call to a `suspend
fun` wrapped in something that is optimized away later, the owner of
the method will be incorrect;
* references to functions returning non-Unit but casted to `() ->
Unit` (allowed by new inference) might in fact not return Unit after
tail call optimization.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
var result: String = ""
|
||||
var proceed: (() -> Unit)? = null
|
||||
|
||||
fun box(): String {
|
||||
async {
|
||||
O().foo(1)
|
||||
O().foo(2)
|
||||
}
|
||||
while (proceed != null) {
|
||||
result += "--;"
|
||||
proceed!!()
|
||||
}
|
||||
if (result != "begin(1);--;end(1);begin(2);--;end(2);done;") return result;
|
||||
return "OK"
|
||||
}
|
||||
|
||||
open class O {
|
||||
open suspend fun foo(x: Int) {
|
||||
result += "begin($x);"
|
||||
sleep()
|
||||
result += "end($x);"
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sleep(): Unit = suspendCoroutine { c ->
|
||||
proceed = { c.resume(Unit) }
|
||||
}
|
||||
|
||||
fun async(f: suspend () -> Unit) {
|
||||
f.startCoroutine(object : Continuation<Unit> {
|
||||
override fun resumeWith(x: Result<Unit>) {
|
||||
result += "done;"
|
||||
proceed = null
|
||||
}
|
||||
override val context = EmptyCoroutineContext
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
// FILE: I.kt
|
||||
|
||||
open class A<T> {
|
||||
suspend fun id(x: T): T = x
|
||||
}
|
||||
|
||||
class B {
|
||||
fun ok() = "OK"
|
||||
}
|
||||
|
||||
// FILE: JavaClass.java
|
||||
|
||||
public class JavaClass extends A<B> {}
|
||||
|
||||
// FILE: main.kt
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
fun box(): String {
|
||||
var result = "fail"
|
||||
suspend {
|
||||
result = JavaClass().id(B()).ok()
|
||||
}.startCoroutine(EmptyContinuation)
|
||||
return result
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
object Dummy
|
||||
|
||||
suspend fun suspect(): Dummy = suspendCoroutineUninterceptedOrReturn {
|
||||
x -> x.resume(Dummy)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res: Any? = null
|
||||
suspend {
|
||||
res = (::suspect as suspend () -> Unit)()
|
||||
}.startCoroutine(EmptyContinuation)
|
||||
return if (res != Unit) "$res" else "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user