Support instantiation of annotations with type parameters
By ignoring type parameters. Since type parameters in annotations are a very limited feature, their sole use is to be able to specify them as KClass argument: annotation class Foo<T: Any>(val bar: KClass<T>). Since we can encounter type param only as a KClass type argument (and never as a property type), simple approach of ignoring them works fine. In that case, since we simply copy property types to synthetic implementation class, its properties in IR start look like this: annotation class FooImpl(override val bar: KClass<T of Foo>). This IR seems to be not completely correct, since FooImpl.bar type contains T of Foo param, which is out of its scope. However, so far I didn't encounter any problems with this during testing and after MR discussion this approach has been considered possible. #KT-59558 Fixed #KT-59036 Fixed
This commit is contained in:
committed by
Space Team
parent
8c795462e1
commit
648c1f4599
@@ -1,6 +1,6 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
|
||||
// (supported: JVM_IR, JS_IR(_E6))
|
||||
// (supported: JVM_IR, JS_IR(_ES6), NATIVE)
|
||||
// Regular JS works too, but without proper hashCode or equals
|
||||
|
||||
// WITH_STDLIB
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// IGNORE_BACKEND: WASM
|
||||
// WASM ticket: KT-59032
|
||||
|
||||
// supported: JVM_IR, JS_IR(_ES6), NATIVE
|
||||
|
||||
// WITH_STDLIB
|
||||
// !LANGUAGE: +InstantiationOfAnnotationClasses
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue as assert
|
||||
|
||||
annotation class One<T>()
|
||||
|
||||
annotation class Two<K, V>(val s: String)
|
||||
annotation class Nesting(val a1: One<Int> = One(), val a2: Two<String, List<String>> = Two("two"))
|
||||
|
||||
annotation class WithKClass<K: Any>(val k: KClass<K>)
|
||||
|
||||
fun box(): String {
|
||||
val a = One<String>()
|
||||
assert(a.toString().endsWith("test.One()"))
|
||||
val t = Two<String, Int>("two")
|
||||
assertEquals("two", t.s)
|
||||
val n = Nesting()
|
||||
assertEquals("two", n.a2.s)
|
||||
val wk = WithKClass(String::class)
|
||||
assert(String::class == wk.k)
|
||||
|
||||
// type parameters don't affect equals
|
||||
assert(Two<String, Int>("two") == Two<Int, String>("two"))
|
||||
assert(WithKClass(Int::class) != WithKClass(String::class))
|
||||
return "OK"
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
// WITH_REFLECT
|
||||
// !LANGUAGE: +InstantiationOfAnnotationClasses
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue as assert
|
||||
|
||||
annotation class WithKClass<K: Any>(val k: KClass<K>)
|
||||
|
||||
// Following can't be called on JS/Native, as on these platforms only `Array::class : KClass<Array<*>>` exists.
|
||||
|
||||
annotation class WithArray<A>(val a: KClass<Array<A>>)
|
||||
|
||||
annotation class Combined<T: Any>(val t: KClass<T>, val w: WithKClass<T>, val wa: WithArray<T>)
|
||||
|
||||
class X
|
||||
|
||||
fun box(): String {
|
||||
val wa = WithArray(Array<String>::class)
|
||||
assert(wa.a.java.isArray)
|
||||
assert(wa.a.java.componentType == String::class.java)
|
||||
assertEquals(WithArray(Array<String>::class), wa)
|
||||
assert(WithArray(Array<Int>::class) != wa)
|
||||
|
||||
val typeParams = WithKClass(X::class).annotationClass.typeParameters
|
||||
assertEquals(1, typeParams.size)
|
||||
|
||||
val c = Combined(X::class, WithKClass(X::class), WithArray(Array<X>::class))
|
||||
assertEquals(X::class, c.t)
|
||||
assertEquals(X::class, c.w.k)
|
||||
assertEquals(X::class.java, c.wa.a.java.componentType)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// IGNORE_DEXING
|
||||
// WITH_STDLIB
|
||||
// !LANGUAGE: +InstantiationOfAnnotationClasses
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
|
||||
package a
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
annotation class Two<K, V>(val s: String)
|
||||
annotation class Nesting(val a2: Two<String, List<String>> = Two("two"))
|
||||
|
||||
annotation class WithKClass<K: Any>(val k: KClass<K>)
|
||||
|
||||
|
||||
// MODULE: app(lib)
|
||||
// FILE: app.kt
|
||||
|
||||
package test
|
||||
|
||||
import a.*
|
||||
import kotlin.test.*
|
||||
|
||||
fun box(): String {
|
||||
val t = Two<String, Int>("two")
|
||||
assertEquals("two", t.s)
|
||||
val n = Nesting()
|
||||
assertEquals("two", n.a2.s)
|
||||
val wk = WithKClass(String::class)
|
||||
assertTrue(String::class == wk.k)
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user