Today I encountered strange behavior while creating some Kotlin generics. Code below illustrates the problem.
MCVE
class Generic<T>(private val initial: T? = null, private val source: (T)->Unit) {
fun test(value: T) = source(value)
}
fun <T> createGeneric(initial: T? = null, source: (T)->Unit) = Generic(initial, source)
fun test() {
val generic = createGeneric(null) { arg: Int -> println(arg) }
generic.test(42)
}
The line generic.test(42) produces error:
The integral literal does not conform to the expected type Nothing
Question: How can T be deduced as Nothing, since I pass { arg: Int -> println(arg) } lambda, which is (Int)->Unit?. I double-checked type of variable generic, and it's deduced as Generic<Nothing>.
Also, if the type is deduced as Nothing, why it allows to pass lambda of type (Int)->Unit as second argument?
Kotlin Playground Example
Because functions are contravariant in their argument, (Int) -> Unit is a subtype of (Nothing) -> Unit. So both arguments are acceptable for T=Nothing and that's what gets inferred.
Yes, they are also both acceptable for T=Int, but Kotlin chooses the more specific type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With