Reflection: fix calling suspend fun returning value class over primitive
#KT-47973 Fixed
This commit is contained in:
committed by
Space Team
parent
6a2cea8a8e
commit
931c2ce47a
+10
-17
@@ -5,7 +5,6 @@
|
|||||||
import kotlin.coroutines.startCoroutine
|
import kotlin.coroutines.startCoroutine
|
||||||
import kotlin.reflect.full.callSuspend
|
import kotlin.reflect.full.callSuspend
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
|
|
||||||
inline class Z(val value: Int)
|
inline class Z(val value: Int)
|
||||||
@@ -32,33 +31,27 @@ private fun run0(f: suspend () -> Int): Int {
|
|||||||
fun box(): String {
|
fun box(): String {
|
||||||
val c = C()
|
val c = C()
|
||||||
|
|
||||||
assertFailsWith<IllegalArgumentException>("Remove assertFailsWith and try again, as this problem may have been fixed.") {
|
run0 {
|
||||||
run0 {
|
C::nonNullConsume.callSuspend(c, Z(1))
|
||||||
C::nonNullConsume.callSuspend(c, Z(1))
|
C::nonNullProduce.callSuspend(c).value
|
||||||
C::nonNullProduce.callSuspend(c).value
|
}.let { assertEquals(1, it) }
|
||||||
}.let { assertEquals(1, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
run0 {
|
run0 {
|
||||||
C::nullableConsume.callSuspend(c, Z(2))
|
C::nullableConsume.callSuspend(c, Z(2))
|
||||||
C::nullableProduce.callSuspend(c)!!.value
|
C::nullableProduce.callSuspend(c)!!.value
|
||||||
}.let { assertEquals(2, it) }
|
}.let { assertEquals(2, it) }
|
||||||
|
|
||||||
assertFailsWith<IllegalArgumentException>("Remove assertFailsWith and try again, as this problem may have been fixed.") {
|
run0 {
|
||||||
run0 {
|
C::nonNull_nonNullConsumeAndProduce.callSuspend(c, Z(3)).value
|
||||||
C::nonNull_nonNullConsumeAndProduce.callSuspend(c, Z(3)).value
|
}.let { assertEquals(3, it) }
|
||||||
}.let { assertEquals(3, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
run0 {
|
run0 {
|
||||||
C::nonNull_nullableConsumeAndProduce.callSuspend(c, Z(4))!!.value
|
C::nonNull_nullableConsumeAndProduce.callSuspend(c, Z(4))!!.value
|
||||||
}.let { assertEquals(4, it) }
|
}.let { assertEquals(4, it) }
|
||||||
|
|
||||||
assertFailsWith<IllegalArgumentException>("Remove assertFailsWith and try again, as this problem may have been fixed.") {
|
run0 {
|
||||||
run0 {
|
C::nullable_nonNullConsumeAndProduce.callSuspend(c, Z(5)).value
|
||||||
C::nullable_nonNullConsumeAndProduce.callSuspend(c, Z(5)).value
|
}.let { assertEquals(5, it) }
|
||||||
}.let { assertEquals(5, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
run0 {
|
run0 {
|
||||||
C::nullable_nullableConsumeAndProduce.callSuspend(c, Z(6))!!.value
|
C::nullable_nullableConsumeAndProduce.callSuspend(c, Z(6))!!.value
|
||||||
|
|||||||
@@ -62,7 +62,17 @@ internal class ValueClassAwareCaller<out M : Member?>(
|
|||||||
private class BoxUnboxData(val argumentRange: IntRange, val unboxParameters: Array<List<Method>?>, val box: Method?)
|
private class BoxUnboxData(val argumentRange: IntRange, val unboxParameters: Array<List<Method>?>, val box: Method?)
|
||||||
|
|
||||||
private val data: BoxUnboxData = run {
|
private val data: BoxUnboxData = run {
|
||||||
val box = descriptor.returnType!!.toInlineClass()?.getBoxMethod(descriptor)
|
val returnType = descriptor.returnType!!
|
||||||
|
val box = if (
|
||||||
|
descriptor is FunctionDescriptor && descriptor.isSuspend &&
|
||||||
|
returnType.substitutedUnderlyingType()?.let { KotlinBuiltIns.isPrimitiveType(it) } == true
|
||||||
|
) {
|
||||||
|
// Suspend functions always return java.lang.Object, and value classes over primitives are already boxed there.
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
returnType.toInlineClass()?.getBoxMethod(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
if (descriptor.isGetterOfUnderlyingPropertyOfValueClass()) {
|
if (descriptor.isGetterOfUnderlyingPropertyOfValueClass()) {
|
||||||
// Getter of the underlying val of a value class is always called on a boxed receiver,
|
// Getter of the underlying val of a value class is always called on a boxed receiver,
|
||||||
// no argument unboxing is required.
|
// no argument unboxing is required.
|
||||||
|
|||||||
Reference in New Issue
Block a user