Reflection: add KVariance, KTypeParameter.{variance,upperBounds,equals,hashCode}

This commit is contained in:
Alexander Udalov
2016-07-22 15:34:54 +03:00
parent 127e7ab5b7
commit 170ea4dead
9 changed files with 272 additions and 3 deletions
@@ -0,0 +1,39 @@
// WITH_REFLECT
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
class A<T>
class B<T>
class Fun {
fun <T> foo(): T = null!!
}
class Fourple<A, B, in C, out D>
fun box(): String {
assertEquals(A::class.typeParameters, A::class.typeParameters)
assertEquals(A::class.typeParameters.single().hashCode(), A::class.typeParameters.single().hashCode())
fun getFoo() = Fun::class.members.single { it.name == "foo" }
assertEquals(getFoo().typeParameters, getFoo().typeParameters)
assertEquals(getFoo().typeParameters.single().hashCode(), getFoo().typeParameters.single().hashCode())
assertNotEquals(A::class.typeParameters.single(), B::class.typeParameters.single())
val fi = Fourple::class.typeParameters
val fj = Fourple::class.typeParameters
for (i in 0..fi.size - 1) {
for (j in 0..fj.size - 1) {
if (i == j) {
assertEquals(fi[i], fj[j])
assertEquals(fi[i].hashCode(), fj[j].hashCode())
} else {
assertNotEquals(fi[i], fj[j])
}
}
}
return "OK"
}
@@ -0,0 +1,23 @@
// WITH_REFLECT
import kotlin.reflect.KVariance
import kotlin.test.assertEquals
class Triple<in A, B, out C> {
fun <T> foo(): T = null!!
}
fun box(): String {
assertEquals(
listOf(
KVariance.IN,
KVariance.INVARIANT,
KVariance.OUT
),
Triple::class.typeParameters.map { it.variance }
)
assertEquals(KVariance.INVARIANT, Triple::class.members.single { it.name == "foo" }.typeParameters.single().variance)
return "OK"
}
@@ -0,0 +1,59 @@
// WITH_REFLECT
import kotlin.reflect.KTypeProjection
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class DefaultBound<T>
class NullableAnyBound<T : Any?>
class NotNullAnyBound<T : Any>
class TwoBounds<T : Cloneable> where T : Comparable<T>
class OtherParameterBound<T : U, U : Number>
class RecursiveGeneric<T : Enum<T>>
class FunctionTypeParameter {
fun <A : Cloneable> foo(): Cloneable = null!!
}
// helper functions to obtain KType instances
fun nullableAny(): Any? = null
fun notNullAny(): Any = null!!
fun box(): String {
assertEquals(listOf(::nullableAny.returnType), DefaultBound::class.typeParameters.single().upperBounds)
assertEquals(listOf(::nullableAny.returnType), NullableAnyBound::class.typeParameters.single().upperBounds)
assertEquals(listOf(::notNullAny.returnType), NotNullAnyBound::class.typeParameters.single().upperBounds)
TwoBounds::class.typeParameters.single().let {
val (cl, cm) = it.upperBounds
assertEquals(Cloneable::class, cl.classifier)
assertEquals(listOf(), cl.arguments)
assertEquals(Comparable::class, cm.classifier)
val cmt = cm.arguments.single()
assertTrue(cmt is KTypeProjection.Invariant)
assertEquals(it, cmt.type!!.classifier)
}
OtherParameterBound::class.typeParameters.let {
val (t, u) = it
assertEquals(u, t.upperBounds.single().classifier)
assertEquals(Number::class, u.upperBounds.single().classifier)
}
FunctionTypeParameter::class.members.single { it.name == "foo" }.let { foo ->
assertEquals(foo.returnType, foo.typeParameters.single().upperBounds.single())
}
val recursiveGenericTypeParameter = RecursiveGeneric::class.typeParameters.single()
val recursiveGenericBound = recursiveGenericTypeParameter.upperBounds.single()
assertEquals(Enum::class, recursiveGenericBound.classifier)
recursiveGenericBound.arguments.single().let { projection ->
assertTrue(projection is KTypeProjection.Invariant)
assertEquals(recursiveGenericTypeParameter, projection.type!!.classifier)
}
return "OK"
}
@@ -0,0 +1,26 @@
// WITH_REFLECT
import kotlin.reflect.KVariance
import kotlin.test.assertEquals
class Fourple<A, B, C, D>
fun foo(): Fourple<String, in String, out String, *> = null!!
fun listOfStrings(): List<String> = null!!
fun box(): String {
assertEquals(
listOf(
KVariance.INVARIANT,
KVariance.IN,
KVariance.OUT,
null
),
::foo.returnType.arguments.map { it.variance }
)
// Declaration-site variance should have no effect on the variance of the type projection:
assertEquals(KVariance.INVARIANT, ::listOfStrings.returnType.arguments.first().variance)
return "OK"
}