As @Михаил Нафталь's answer demonstrates, a type being reified
is very limiting, so it is critical that the language requires you to be explicit about exactly which types should be reified. Reification requires the type to be known at compile time, so functions with reified types can only be called from functions where that type is not a non-reified generic type.
Someone could argue, well then, only assume it is reified if T::class
happens to be used inside this inline function and otherwise treat it as not reified. But that would mean your effective function signature could change just by changing the contents of the function without changing its declaration. That would make it very easy to accidentally change a function signature, which is a recipe for disaster in the future. For example, suppose I have this function:
inline fun <T> registerList(list: List<T>) { // T is not reified
myProtectedRegistryList.add(list)
}
and so it is used in other places in my app, or by users of my library like this:
class Foo<T>(val data: List<T>) {
init {
registerList(data)
}
}
// or
fun foo(data: List<T>) {
registerList(data)
}
// or
class Bar<T> {
var barRegister: (List<T>)->Unit = ::registerList
}
Later I modify my function without changing its declaration:
// In hypothetical Kotlin with implicit reification, T is now reified:
inline fun <T> registerList(list: List<T>) { // This line of code unchanged!
myProtectedRegistryMap.put(T::class, list)
}
Now I have broken the code everywhere that it was used like one of the examples above. So, by the language requiring you to change the declaration to change the signature, you are forced to think about the external impact of modifying your function. You know that if you refactor the declaration of any function, that is the only way its usability is affected at call sites.
The Kotlin design philosophy on this kind of matter is to be conservative and require explicit declarations. It's the same reason functional interfaces have to be explicitly marked with the fun
keyword even if they currently only have a single abstract function, and classes/functions are final by default.