Messing around with the following example code made me realize I'm confused about when Kotlin infers a platform type:
inline fun <reified U, V> LiveData<U>.map(crossinline f: (U) -> V): LiveData<V> {
val result = MediatorLiveData<V>()
result.addSource(this) { u -> // u: U!
if (u is U) {
result.value = f(u)
}
}
return result
}
val x = MutableLiveData<Int>()
val y = x.map { it + 1 }
x.value = 1 // ok
x.value = null // will eventually crash from doing null + 1
My hope was that this use of reified+crossinline would prevent the map function from calling f when u is null, because it would check if null is Int. Interestingly though, the null sneaks past the check.
I thought I must be misunderstanding how reified+crossinline works, but it seems that what's actually at issue is type inference: U seems to be inferred as Int!, not Int. For example, manually specifying map's type parameters gets things to work:
val y = x.map<Int, Int> { it + 1 }
So. Why was Kotlin infering a platform type above? (After all, x has inferred type MutableLiveData<Int>, not MutableLiveData<Int!>.) Is there a way to not infer a platform type, aside from doing the inference yourself?