Kotlin incorrectly infers nullable Enum return type when a function call is passed as an argument to another function

Here’s an example

fun main() {
    acceptEnum(inferType())
}

fun acceptEnum(value: MyEnum?) {}

fun <R : Enum<R>?> inferType(): R = TODO()

enum class MyEnum {
    VALUE
}

inferType() infers its return type and bounds it to be a generic nullable enum. acceptEnum() has a nullable enum parameter. When we write acceptEnum(inferType()) , everything’s fine. But if we add one more parameter to acceptEnum() and pass inferType() there again, here’s what happens:

fun main() {
    // first inferType() does not compile with an error:
    // Type mismatch: inferred type is MyEnum? but MyEnum was expected
    acceptEnum(inferType(), inferType())
}

fun acceptEnum(value: MyEnum?, value2: MyEnum?) {}

If we add more parameters, every inferType() call except the last one produces this error.

Is this a compiler bug or am I doing something wrong?

I tried with following code

enum class MyEnum { V }

fun main() {
    acceptEnum(inferTypeM())
    acceptEnum(inferTypeMN())
    acceptEnum(inferTypeR()) // Type mismatch: inferred type is MyEnum? but MyEnum was expected
    acceptEnum(inferTypeRN()) // Type mismatch: inferred type is MyEnum? but MyEnum was expected
}

fun acceptEnum(value: MyEnum?) {}

fun inferTypeM(): MyEnum {
    return null // Null can not be a value of a non-null type MyEnum
}

fun inferTypeMN(): MyEnum? {
    return null
}

fun <R : Enum<R>?> inferTypeR(): R {
    return null //Null can not be a value of a non-null type R
}

fun <R : Enum<R>?> inferTypeRN(): R? {
    return null
}

It seems like Kotlin thinks generic type R is not nullable.

And for multi-arguments function

fun main() {
    acceptEnum2(inferTypeM(), inferTypeM())
    acceptEnum2(inferTypeMN(), inferTypeMN())

    // Type mismatch.
    // Required: MyEnum
    // Found: MyEnum?
    acceptEnum2(inferTypeR(), inferTypeR())

    // Type mismatch.
    // Required: MyEnum
    // Found: MyEnum?
    acceptEnum2(inferTypeRN(), inferTypeRN())
}

I think it’s the compiler that makes mistakes.

I’ve created an issue https://youtrack.jetbrains.com/issue/KT-50232