首页 文章

与普通和自动类型转换相关的Kotlin werid编译错误

提问于
浏览
0

我认为这段代码应该编译:

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 { this@apply.addAll(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()
    }

这是对Google Guava的Invokable的方便参考 . 简要给出了 Invokable 的定义 .

上面的代码应该编译所有罚款,但编译器产生3个奇怪的消息,这里是日志输出(经过适当的规范化):

e:/path/to/source.kt:(34,44):类型推断失败:val Invokable.declaringClass:Class!不能应用于接收器:T#2(描述符的类型参数)参数:()e:/path/to/source.kt:(35,44):类型推断失败:val Invokable.modifiers:Int不能应用于receiver:T#2(描述符的类型参数)参数:()e:/path/to/source.kt:(37,44):类型推断失败:val Invokable.declaringClass:Class!不能应用于接收器:T#2(描述符的类型参数)参数:()

解决方案很简单:将其分配给变量并使用该局部变量 . 没有手动类型转换或其他困扰的东西,它将编译 . 但我很感兴趣,如果这是kotlin编译器的错误或我错过了一些关于kotlin泛型的信息

编辑:工作代码:

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 { this@apply.addAll(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()
    }

这已经submitted to JetBrains但他们还没有回应,所以我会保持这个开放,直到他们验证或有人上来责骂我的愚蠢 .

1 回答

  • 0

    智能投射似乎不够聪明 . 但你可以使用以下方法给它一个提示:

    val <T : AccessibleObject> T.descriptor: Descriptor
    get() = when (this) {
        is Invokable<*, *> -> {
            Descriptor(this.declaringClass,
                    this.modifiers,
                    info,
                    this.declaringClass.info)
        }
        else -> throw AssertionError()
    }
    

    不需要使用val的东西 . 你只需要给它一些“东西”就可以了 . 当没有什么可以在IDE上“突出显示”时,它可能会很乱

相关问题