IC & Coroutines: Do not box suspend operator fun invoke receiver
if it is called using parens and not by calling 'invoke' method. Use underlying type when calling continuation constructor if suspend function is method inside inline class. #KT-43505 Fixed #KT-39437 Fixed
This commit is contained in:
+62
@@ -0,0 +1,62 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(Continuation(EmptyCoroutineContext) {
|
||||
it.getOrThrow()
|
||||
})
|
||||
}
|
||||
|
||||
inline class IC(val a: Any?)
|
||||
|
||||
class GetResult {
|
||||
suspend operator fun invoke() = IC("OK")
|
||||
}
|
||||
|
||||
inline class IC1(val a: String) {
|
||||
suspend operator fun invoke() = IC(a)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
val getResult = GetResult()
|
||||
res = getResult().a as String
|
||||
}
|
||||
if (res != "OK") return "FAIL 1 $res"
|
||||
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
val getResult = GetResult()
|
||||
res = getResult.invoke().a as String
|
||||
}
|
||||
if (res != "OK") return "FAIL 2 $res"
|
||||
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
res = GetResult()().a as String
|
||||
}
|
||||
if (res != "OK") return "FAIL 3 $res"
|
||||
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
val getResult = IC1("OK")
|
||||
res = getResult().a as String
|
||||
}
|
||||
if (res != "OK") return "FAIL 4 $res"
|
||||
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
val getResult = IC1("OK")
|
||||
res = getResult.invoke().a as String
|
||||
}
|
||||
if (res != "OK") return "FAIL 5 $res"
|
||||
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
res = IC1("OK")().a as String
|
||||
}
|
||||
if (res != "OK") return "FAIL 6 $res"
|
||||
return res
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(Continuation(EmptyCoroutineContext) {
|
||||
it.getOrThrow()
|
||||
})
|
||||
}
|
||||
|
||||
inline class IC(val a: Any?)
|
||||
|
||||
var c: Continuation<Any>? = null
|
||||
|
||||
suspend fun <T> suspendMe(): T = suspendCoroutine {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
c = it as Continuation<Any>
|
||||
}
|
||||
|
||||
class GetResult {
|
||||
suspend operator fun invoke(): IC = suspendMe()
|
||||
}
|
||||
|
||||
inline class IC1(val a: String) {
|
||||
suspend operator fun invoke(): IC = suspendMe()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
val getResult = GetResult()
|
||||
res = getResult().a as String
|
||||
}
|
||||
c?.resume(IC("OK"))
|
||||
if (res != "OK") return "FAIL 1 $res"
|
||||
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
val getResult = GetResult()
|
||||
res = getResult.invoke().a as String
|
||||
}
|
||||
c?.resume(IC("OK"))
|
||||
if (res != "OK") return "FAIL 2 $res"
|
||||
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
res = GetResult()().a as String
|
||||
}
|
||||
c?.resume(IC("OK"))
|
||||
if (res != "OK") return "FAIL 3 $res"
|
||||
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
val getResult = IC1("OK")
|
||||
res = getResult().a as String
|
||||
}
|
||||
c?.resume(IC("OK"))
|
||||
if (res != "OK") return "FAIL 4 $res"
|
||||
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
val getResult = IC1("OK")
|
||||
res = getResult.invoke().a as String
|
||||
}
|
||||
c?.resume(IC("OK"))
|
||||
if (res != "OK") return "FAIL 5 $res"
|
||||
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
res = IC1("OK")().a as String
|
||||
}
|
||||
c?.resume(IC("OK"))
|
||||
if (res != "OK") return "FAIL 6 $res"
|
||||
return res
|
||||
}
|
||||
Vendored
+78
@@ -0,0 +1,78 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import helpers.*
|
||||
|
||||
var result = "FAIL"
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(handleExceptionContinuation {
|
||||
result = it.message!!
|
||||
})
|
||||
}
|
||||
|
||||
inline class IC(val a: Any?)
|
||||
|
||||
var c: Continuation<Any>? = null
|
||||
|
||||
suspend fun <T> suspendMe(): T = suspendCoroutine {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
c = it as Continuation<Any>
|
||||
}
|
||||
|
||||
class GetResult {
|
||||
suspend operator fun invoke(): IC = suspendMe()
|
||||
}
|
||||
|
||||
inline class IC1(val a: String) {
|
||||
suspend operator fun invoke(): IC = suspendMe()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
val getResult = GetResult()
|
||||
getResult()
|
||||
}
|
||||
c?.resumeWithException(IllegalStateException("OK"))
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
result = "FAIL 2"
|
||||
builder {
|
||||
val getResult = GetResult()
|
||||
getResult.invoke()
|
||||
}
|
||||
c?.resumeWithException(IllegalStateException("OK"))
|
||||
if (result != "OK") return "FAIL 2 $result"
|
||||
|
||||
result = "FAIL 3"
|
||||
builder {
|
||||
GetResult()()
|
||||
}
|
||||
c?.resumeWithException(IllegalStateException("OK"))
|
||||
if (result != "OK") return "FAIL 3 $result"
|
||||
|
||||
result = "FAIL 4"
|
||||
builder {
|
||||
val getResult = IC1("OK")
|
||||
getResult()
|
||||
}
|
||||
c?.resumeWithException(IllegalStateException("OK"))
|
||||
if (result != "OK") return "FAIL 4 $result"
|
||||
|
||||
result = "FAIL 5"
|
||||
builder {
|
||||
val getResult = IC1("OK")
|
||||
getResult.invoke()
|
||||
}
|
||||
c?.resumeWithException(IllegalStateException("OK"))
|
||||
if (result != "OK") return "FAIL 5 $result"
|
||||
|
||||
result = "FAIL 6"
|
||||
builder {
|
||||
IC1("OK")()
|
||||
}
|
||||
c?.resumeWithException(IllegalStateException("OK"))
|
||||
if (result != "OK") return "FAIL 6 $result"
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user