Home > Back-end >  Kotlin custom Scope function return type not behaving as expected
Kotlin custom Scope function return type not behaving as expected

Time:06-19

this custom function call's a lambda block when null. I expected the function definition below to enforce the same return type. : T
Is their a way to enforce that be block returns type T ?

inline fun <T> T?.whenNull(block: () -> T): T {
    if (this == null) {
        return block() //accepts any return type
    } else {
        return this
    }
}

fun main() {
    val x : Int? = null
    println(x ?: 42)
    println(x.whenNull { 42 })
    println(x.whenNull { "why is kotlin not enforcing return of the same type?" })
}

CodePudding user response:

Interestingly, when passing this to the block the type is preserved and works as expected.

inline fun <T> T?.whenNullAlt(block: (T?) -> T): T {
    if (this == null) {
        return block(this) // "this" is superfluous, but enforces same return type
    } else {
        return this
    }
}

fun main() {
    val x : Int? = null
    println(x.whenNullAlt { 42 })
    println(x.whenNullAlt { "does not compile" })  
}

CodePudding user response:

T in the second whenAll call is being inferred as Any. Imagine that all occurrences of T are replaced Any, the call would be valid, wouldn't you agree? Int and String are both subtypes of Any, after all.

inline fun Any?.whenNull(block: () -> Any): Any {
    if (this == null) {
        return block()
    } else {
        return this
    }
}

fun main() {
    println(x.whenNull { "why is kotlin not enforcing return of the same type?" })
}

Basically, the Kotlin compiler is "trying too hard" here to make your code compile, and infers an unexpected type for your type parameter.


There exists an internal annotation @kotlin.internal.InputTypesOnly that would prevent your code from compiling if the type inferred is not mentioned in one of the input types (parameter types, receiver type, etc) of the function.

In this case, the input type is just Int?, and T is inferred to be Any, so it would be make your code not compile as expected. Unfortunately though, this annotation is internal, and you cannot use it :( KT-13198 is the ticket about making it public.

  • Related