https://kotlinlang.org logo
k

KoxAlen

01/24/2020, 9:57 AM
Mmm not sure if this is the proper channel to ask about reified behaviour... I have the following code
Copy code
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import kotlin.reflect.typeOf

data class Definition(
    val name: String
)

@ExperimentalStdlibApi
fun main() {
    val parsed1: List<Definition> = parseGood("")
    val parsed2: List<Definition> = parseBad("")
}

@ExperimentalStdlibApi
private inline fun <reified T> parseGood(blob: String): T {
    return readValue(blob)
}

@ExperimentalStdlibApi
private inline fun <reified T> parseBad(blob: String): List<T> {
    return readValue(blob)
}

@ExperimentalStdlibApi
private inline fun <reified T> readValue(blob: String): T {
    println(typeOf<T>())
    val type = object : TypeHolder<T>() {}.type
    println(type)
    //Do magic with type and return a T
    return listOf(Definition("foo")) as T
}

open class TypeHolder<T> protected constructor() {
    private var _type: Type
    val type get() = _type

    init {
        val superClass = javaClass.genericSuperclass
        _type = (superClass as ParameterizedType).actualTypeArguments[0]
    }
}
This prints
Copy code
kotlin.collections.List<Definition>
java.util.List<? extends Definition>
kotlin.collections.List<Definition>
java.util.List<? extends T>
So for
typeOf
T is the same in both cases but for the subclass generation one has the signature with the real type and the other one doesn't. Is this a bug, or I'm missing something?
In the generated bytecode
Copy code
// ================TestKt$main$$inlined$parseGood$1.class =================
// class version 50.0 (50)
// access flags 0x31
// signature LTypeHolder<Ljava/util/List<+LDefinition;>;>;
// declaration: TestKt$main$$inlined$parseGood$1 extends TypeHolder<java.util.List<? extends Definition>>
and
Copy code
// ================TestKt$parseBad$$inlined$readValue$1.class =================
// class version 50.0 (50)
// access flags 0x31
// signature LTypeHolder<Ljava/util/List<+TT;>;>;
// declaration: TestKt$parseBad$$inlined$readValue$1 extends TypeHolder<java.util.List<? extends T>>
u

udalov

01/27/2020, 3:39 PM
java.util.List<? extends T>
looks like a bug, since
T
is undeclared at this point
k

KoxAlen

01/28/2020, 10:18 AM
🙏 1
7 Views