KT-27524 Don't box (some) inline classes in suspend fun return
If an inline class is mapped to a reference type (or an array), it's Ok to treat JVM view on a suspend function as returning a value of corresponding inline class (although in reality it returns 'Any?' because of COROUTINE_SUSPENDED).
This commit is contained in:
+97
@@ -0,0 +1,97 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val s: Any)
|
||||
|
||||
class Test1() {
|
||||
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(ss: IC): IC = IC(ss.s)
|
||||
|
||||
suspend fun <T> quz(t: T): T = t
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz(IC("OK"))))
|
||||
}
|
||||
|
||||
suspend fun test(): Any = bar().s
|
||||
}
|
||||
|
||||
|
||||
class Test2 {
|
||||
|
||||
suspend fun foo(value: IC): IC {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(s: String): IC = IC(s)
|
||||
|
||||
suspend fun quz(): String = "OK"
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz()))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(IC("OK"))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var result: Any = "FAIL"
|
||||
builder {
|
||||
result = Test1().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
result = "FAIL2"
|
||||
|
||||
builder {
|
||||
result = Test2().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 2 $result"
|
||||
|
||||
result = "FAIL 3"
|
||||
|
||||
builder {
|
||||
result = Test3().test()
|
||||
}
|
||||
|
||||
return result as String
|
||||
}
|
||||
Vendored
+100
@@ -0,0 +1,100 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class I0(val x: Any)
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val s: I0)
|
||||
|
||||
class Test1() {
|
||||
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(ss: IC): IC = IC(ss.s)
|
||||
|
||||
suspend fun <T> quz(t: T): T = t
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz(IC(I0("OK")))))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s.x
|
||||
}
|
||||
|
||||
|
||||
class Test2 {
|
||||
|
||||
suspend fun foo(value: IC): IC {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(s: String): IC = IC(I0(s))
|
||||
|
||||
suspend fun quz(): String = "OK"
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz()))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s.x
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(IC(I0("OK")))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s.x
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var result: Any = "FAIL"
|
||||
builder {
|
||||
result = Test1().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
result = "FAIL2"
|
||||
|
||||
builder {
|
||||
result = Test2().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 2 $result"
|
||||
|
||||
result = "FAIL 3"
|
||||
|
||||
builder {
|
||||
result = Test3().test()
|
||||
}
|
||||
|
||||
return result as String
|
||||
}
|
||||
Vendored
+103
@@ -0,0 +1,103 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class I0(val x: Int)
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val s: I0)
|
||||
|
||||
class Test1() {
|
||||
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(ss: IC): IC = IC(ss.s)
|
||||
|
||||
suspend fun <T> quz(t: T): T = t
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz(IC(I0(42)))))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s.x
|
||||
}
|
||||
|
||||
|
||||
class Test2 {
|
||||
|
||||
suspend fun foo(value: IC): IC {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(s: Int): IC = IC(I0(s))
|
||||
|
||||
suspend fun quz() = 42
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz()))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s.x
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(IC(I0(42)))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s.x
|
||||
}
|
||||
|
||||
fun Int.toBoxResult() =
|
||||
if (this == 42) "OK" else toString()
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var result: Any = "FAIL"
|
||||
builder {
|
||||
result = Test1().test().toBoxResult()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
result = "FAIL2"
|
||||
|
||||
builder {
|
||||
result = Test2().test().toBoxResult()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 2 $result"
|
||||
|
||||
result = "FAIL 3"
|
||||
|
||||
builder {
|
||||
result = Test3().test().toBoxResult()
|
||||
}
|
||||
|
||||
return result as String
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val s: Int)
|
||||
|
||||
class Test1() {
|
||||
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(ss: IC): IC = IC(ss.s)
|
||||
|
||||
suspend fun <T> quz(t: T): T = t
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz(IC(42))))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
|
||||
class Test2 {
|
||||
|
||||
suspend fun foo(value: IC): IC {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(s: Int): IC = IC(s)
|
||||
|
||||
suspend fun quz(): Int = 42
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz()))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(IC(42))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
fun Int.toBoxResult() =
|
||||
if (this == 42) "OK" else toString()
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var result: String = "FAIL"
|
||||
builder {
|
||||
result = Test1().test().toBoxResult()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
result = "FAIL2"
|
||||
|
||||
builder {
|
||||
result = Test2().test().toBoxResult()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 2 $result"
|
||||
|
||||
result = "FAIL 3"
|
||||
|
||||
builder {
|
||||
result = Test3().test().toBoxResult()
|
||||
}
|
||||
|
||||
return result as String
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val s: Long)
|
||||
|
||||
class Test1() {
|
||||
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(ss: IC): IC = IC(ss.s)
|
||||
|
||||
suspend fun <T> quz(t: T): T = t
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz(IC(42L))))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
|
||||
class Test2 {
|
||||
|
||||
suspend fun foo(value: IC): IC {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(s: Long): IC = IC(s)
|
||||
|
||||
suspend fun quz() = 42L
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz()))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(IC(42L))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
fun Long.toBoxResult() =
|
||||
if (this == 42L) "OK" else toString()
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var result: String = "FAIL"
|
||||
builder {
|
||||
result = Test1().test().toBoxResult()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
result = "FAIL2"
|
||||
|
||||
builder {
|
||||
result = Test2().test().toBoxResult()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 2 $result"
|
||||
|
||||
result = "FAIL 3"
|
||||
|
||||
builder {
|
||||
result = Test3().test().toBoxResult()
|
||||
}
|
||||
|
||||
return result as String
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val s: Any?)
|
||||
|
||||
class Test1() {
|
||||
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(ss: IC): IC = IC(ss.s)
|
||||
|
||||
suspend fun <T> quz(t: T): T = t
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz(IC("OK"))))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
|
||||
class Test2 {
|
||||
|
||||
suspend fun foo(value: IC): IC {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(s: String): IC = IC(s)
|
||||
|
||||
suspend fun quz(): String = "OK"
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(qux(quz()))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return foo(IC("OK"))
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var result: Any? = "FAIL"
|
||||
builder {
|
||||
result = Test1().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
result = "FAIL2"
|
||||
|
||||
builder {
|
||||
result = Test2().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 2 $result"
|
||||
|
||||
result = "FAIL 3"
|
||||
|
||||
builder {
|
||||
result = Test3().test()
|
||||
}
|
||||
|
||||
return result as String
|
||||
}
|
||||
Vendored
+103
@@ -0,0 +1,103 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val s: String)
|
||||
|
||||
class Test1() {
|
||||
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(ss: IC): IC = IC(ss.s)
|
||||
|
||||
suspend fun <T> quz(t: T): T = t
|
||||
|
||||
suspend fun bar(): IC {
|
||||
run {
|
||||
return foo(qux(quz(IC("OK"))))
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
|
||||
class Test2 {
|
||||
|
||||
suspend fun foo(value: IC): IC {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(s: String): IC = IC(s)
|
||||
|
||||
suspend fun quz(): String = "OK"
|
||||
|
||||
suspend fun bar(): IC {
|
||||
run {
|
||||
return foo(qux(quz()))
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bar(): IC {
|
||||
run {
|
||||
return foo(IC("OK"))
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var result = "FAIL"
|
||||
builder {
|
||||
result = Test1().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
result = "FAIL2"
|
||||
|
||||
builder {
|
||||
result = Test2().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 2 $result"
|
||||
|
||||
result = "FAIL 3"
|
||||
|
||||
builder {
|
||||
result = Test3().test()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val s: String)
|
||||
|
||||
fun suspendFunId(block: suspend () -> IC) = block
|
||||
|
||||
class Test1() {
|
||||
|
||||
suspend fun <T> foo(value: T): T {
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
it.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun qux(ss: IC): IC = IC(ss.s)
|
||||
|
||||
suspend fun <T> quz(t: T): T = t
|
||||
|
||||
suspend fun bar(): IC {
|
||||
return suspendFunId { foo(qux(quz(IC("OK")))) }()
|
||||
}
|
||||
|
||||
suspend fun test() = bar().s
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
var result = "FAIL"
|
||||
builder {
|
||||
result = Test1().test()
|
||||
}
|
||||
|
||||
if (result != "OK") return "FAIL 1 $result"
|
||||
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user