I think this code snippet should compile:
package bug
import java.lang.reflect.*
data class Descriptor(val clazz: Class<*>, val modifiers: Int, val info: List<String>) {
constructor(clazz: Class<*>, modifiers: Int, vararg info: List<String>) :
this(clazz, modifiers, mutableListOf<String>().apply { info.forEach { [email protected](it) } })
}
private val AnnotatedElement.info: List<String>
get() = getAnnotation(Info::class.java)?.values?.toList() ?: listOf<String>()
annotation class Info(val values: Array<String>)
/**
* A simple abstraction of com.google.common.reflect.Invokable of Guava 20.0.
* https://github.com/google/guava/blob/v20.0/guava/src/com/google/common/reflect/Invokable.java
*/
abstract class Invokable<T, R> : AccessibleObject(), Member, GenericDeclaration
val <T : AccessibleObject> T.descriptor: Descriptor
get() = when (this) {
is Invokable<*, *> ->
Descriptor(declaringClass,
modifiers,
info,
declaringClass.info)
else -> throw AssertionError()
}
Here is a convenient reference to Google Guava's Invokable. Brief Invokable
definition is given.
The above code should compile all fine but compiler yields 3 weird message, here is the log output (after proper normalization):
e: /path/to/source.kt: (34, 44): Type inference failed: val Invokable.declaringClass: Class! cannot be applied to receiver: T#2 (type parameter of descriptor) arguments: ()
e: /path/to/source.kt: (35, 44): Type inference failed: val Invokable.modifiers: Int cannot be applied to receiver: T#2 (type parameter of descriptor) arguments: ()
e: /path/to/source.kt: (37, 44): Type inference failed: val Invokable.declaringClass: Class! cannot be applied to receiver: T#2 (type parameter of descriptor) arguments: ()
The solution is simple: assign this to a variable and use that local variable. No manual type cast or other bothering stuff and it will compile. But I'm interested if this is a bug of kotlin compiler or I'm missing some info about kotlin generics
EDIT: Working code:
package solution
import java.lang.reflect.*
data class Descriptor(val clazz: Class<*>, val modifiers: Int, val info: List<String>) {
constructor(clazz: Class<*>, modifiers: Int, vararg info: List<String>) :
this(clazz, modifiers, mutableListOf<String>().apply { info.forEach { [email protected](it) } })
}
private val AnnotatedElement.info: List<String>
get() = getAnnotation(Info::class.java)?.values?.toList() ?: listOf<String>()
annotation class Info(val values: Array<String>)
/**
* A simple abstraction of com.google.common.reflect.Invokable of Guava 20.0.
* https://github.com/google/guava/blob/v20.0/guava/src/com/google/common/reflect/Invokable.java
*/
abstract class Invokable<T, R> : AccessibleObject(), Member, GenericDeclaration
val <T : AccessibleObject> T.descriptor: Descriptor
get() = when (this) {
is Invokable<*, *> -> {
val o = this // <---------------------------------CHANGES BEGIN FROM THIS LINE
Descriptor(o.declaringClass,
o.modifiers,
info,
o.declaringClass.info)
}
else -> throw AssertionError()
}
This has been submitted to JetBrains but they didn't respond yet, so I will keep this open until they verified or someone come up scolding my stupidness.
foo
? Please show its declaration – voddanval Invokable.declaringClass
anywhere. Could you provide that code too? – voddanInvokable
. Thanks! – voddan