Reified casting of Class/KClass?


#1

Is there a way to prevent the unchecked cast warning in the following example.

inline fun <reified T: Any> create(gson: Gson): TypeAdapter<T>? {
     return when {
         T::class == AppState::class -> {
             val adapter: TypeAdapter<AppState> = MyAdapter()
         
             /* this is reported as unchecked */
             return adapter as TypeAdapter<T>
         }
         else -> null
     }
}

Is there a way to lose the cast at all, because all the type info should be present.

Thanks!


#2

Not at this time. Comparing two KClass variables does not affect smart casts.


#3

Ok, but when I use a java-class the type-cast works, just the cast back to T doesn’t:

fun <T> create(cls: Class<T>): TypeAdapter<T>? {

    if (cls == AppState::class.java) {
        /* smart cast works */
        val cls2: Class<AppState> = cls
        
        val adapter: TypeAdapter<AppState> = ...
        
        /* doesn't work */
        return adapter as TypeAdapter<T>

    }
    return null
}

Is this some fundamental problem with generics or could type-inference here be implemented?


#4

The problem here is in definition of smart cast. In kotlin smart cast means that for some instance we know better type(because of if checks or something like that). So, when we check, that cls == AppState::class.java then we know, that instance inside variable cls has type Class<AppState>.

Actually, after check cls == AppState::class.java we know, that generic parameter T is AppState and, because of this,
TypeAdapter<AppState> is subtype of TypeAdapter<T>. But such analysis is complex and it is not just usual smart cast.
May be we implement it in far future, but not today.


#5

@fab1an So, it’s better to file as issue to track this request.


#6

Reported https://youtrack.jetbrains.com/issue/KT-13646