Support 'call' for primary value of an inline class

Getter of a primary value of an inline class belongs to the box class.
Its arguments should not be unboxed when the method is called.
However, its result might require boxing if it's an inline class value.

When we have an internal primary value, there's no getter method.
In fact, we can use box/unbox methods for inline class directly
(don't forget to box the result, it may be an inline class type value).

 #KT-26748
This commit is contained in:
Dmitry Petrov
2018-11-08 16:27:32 +03:00
parent 78ee48e1cd
commit 99d8f2eb0c
15 changed files with 369 additions and 36 deletions
@@ -0,0 +1,39 @@
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
// WITH_REFLECT
import kotlin.test.assertEquals
inline class Z(internal val x: Int)
inline class Z2(internal val x: Z)
inline class L(internal val x: Long)
inline class L2(internal val x: L)
inline class A(internal val x: Any?)
inline class A2(internal val x: A)
fun box(): String {
assertEquals(42, Z::x.call(Z(42)))
assertEquals(42, Z(42)::x.call())
assertEquals(1234L, L::x.call(L(1234L)))
assertEquals(1234L, L(1234L)::x.call())
assertEquals("abc", A::x.call(A("abc")))
assertEquals("abc", A("abc")::x.call())
assertEquals(null, A::x.call(A(null)))
assertEquals(null, A(null)::x.call())
assertEquals(Z(42), Z2::x.call(Z2(Z(42))))
assertEquals(Z(42), Z2(Z(42))::x.call())
assertEquals(L(1234L), L2::x.call(L2(L(1234L))))
assertEquals(L(1234L), L2(L(1234L))::x.call())
assertEquals(A("abc"), A2::x.call(A2(A("abc"))))
assertEquals(A("abc"), A2(A("abc"))::x.call())
assertEquals(A(null), A2::x.call(A2(A(null))))
assertEquals(A(null), A2(A(null))::x.call())
return "OK"
}
@@ -0,0 +1,39 @@
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
// WITH_REFLECT
import kotlin.test.assertEquals
inline class Z(val x: Int)
inline class Z2(val x: Z)
inline class L(val x: Long)
inline class L2(val x: L)
inline class A(val x: Any?)
inline class A2(val x: A)
fun box(): String {
assertEquals(42, Z::x.call(Z(42)))
assertEquals(42, Z(42)::x.call())
assertEquals(1234L, L::x.call(L(1234L)))
assertEquals(1234L, L(1234L)::x.call())
assertEquals("abc", A::x.call(A("abc")))
assertEquals("abc", A("abc")::x.call())
assertEquals(null, A::x.call(A(null)))
assertEquals(null, A(null)::x.call())
assertEquals(Z(42), Z2::x.call(Z2(Z(42))))
assertEquals(Z(42), Z2(Z(42))::x.call())
assertEquals(L(1234L), L2::x.call(L2(L(1234L))))
assertEquals(L(1234L), L2(L(1234L))::x.call())
assertEquals(A("abc"), A2::x.call(A2(A("abc"))))
assertEquals(A("abc"), A2(A("abc"))::x.call())
assertEquals(A(null), A2::x.call(A2(A(null))))
assertEquals(A(null), A2(A(null))::x.call())
return "OK"
}
@@ -0,0 +1,39 @@
// IGNORE_BACKEND: JVM_IR, JS_IR, JS, NATIVE
// WITH_REFLECT
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
inline class Z1(val publicX: Int) {
companion object {
val publicXRef = Z1::publicX
val publicXBoundRef = Z1(42)::publicX
}
}
inline class Z2(internal val internalX: Int) {
companion object {
val internalXRef = Z2::internalX
val internalXBoundRef = Z2(42)::internalX
}
}
inline class Z3(private val privateX: Int) {
companion object {
val privateXRef = Z3::privateX
val privateXBoundRef = Z3(42)::privateX
}
}
fun box(): String {
assertEquals("getPublicX", Z1.publicXRef.javaGetter!!.name)
assertEquals("getPublicX", Z1.publicXBoundRef.javaGetter!!.name)
assertEquals(null, Z2.internalXRef.javaGetter)
assertEquals(null, Z2.internalXBoundRef.javaGetter)
assertEquals(null, Z3.privateXRef.javaGetter)
assertEquals(null, Z3.privateXBoundRef.javaGetter)
return "OK"
}
@@ -0,0 +1,60 @@
// IGNORE_BACKEND: JVM_IR, JS_IR, JS, NATIVE
// WITH_REFLECT
import kotlin.reflect.KCallable
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
inline class Z1(val publicX: Int) {
companion object {
val publicXRef = Z1::publicX
val publicXBoundRef = Z1(42)::publicX
}
}
inline class Z2(internal val internalX: Int) {
companion object {
val internalXRef = Z2::internalX
val internalXBoundRef = Z2(42)::internalX
}
}
inline class Z3(private val privateX: Int) {
companion object {
val privateXRef = Z3::privateX
val privateXBoundRef = Z3(42)::privateX
}
}
inline class ZZ(val x: Z1)
fun KCallable<*>.getJavaTypesOfParams() = parameters.map { it.type.javaType }.toString()
fun KCallable<*>.getJavaTypeOfResult() = returnType.javaType.toString()
fun box(): String {
assertEquals("[class Z1]", Z1.publicXRef.getJavaTypesOfParams())
assertEquals("int", Z1.publicXRef.getJavaTypeOfResult())
assertEquals("[]", Z1.publicXBoundRef.getJavaTypesOfParams())
assertEquals("int", Z1.publicXBoundRef.getJavaTypeOfResult())
assertEquals("[class Z2]", Z2.internalXRef.getJavaTypesOfParams())
assertEquals("int", Z2.internalXRef.getJavaTypeOfResult())
assertEquals("[]", Z2.internalXBoundRef.getJavaTypesOfParams())
assertEquals("int", Z2.internalXBoundRef.getJavaTypeOfResult())
assertEquals("[class Z3]", Z3.privateXRef.getJavaTypesOfParams())
assertEquals("int", Z3.privateXRef.getJavaTypeOfResult())
assertEquals("[]", Z3.privateXBoundRef.getJavaTypesOfParams())
assertEquals("int", Z3.privateXBoundRef.getJavaTypeOfResult())
assertEquals("[class ZZ]", ZZ::x.getJavaTypesOfParams())
// KT-28170
assertEquals("int", ZZ::x.getJavaTypeOfResult())
return "OK"
}