为什么编译器认为if语句是表达式?

Dod*_*ion 6 kotlin

我有这个方法比较排序列表,并告诉你列表2中哪些项目从列表2中丢失,反之亦然,在O(N)时间:

fun <T : Comparable<T>> compareSortedLists(
        list1: Iterable<T>,
        list2: Iterable<T>,
        onlyInList1: MutableCollection<T>,
        onlyInList2: MutableCollection<T>) {
    val it1 = PeekingIterator(list1.iterator())
    val it2 = PeekingIterator(list2.iterator())
    while (it1.hasNext() && it2.hasNext()) {
        val comp = it1.peek().compareTo(it2.peek())
        if (comp < 0)       // <-- ERROR: type inference failure
            onlyInList1.add(it1.next())
        else if (comp > 0)
            onlyInList2.add(it2.next())
        else {
            it1.next()
            it2.next()      // <---- Error: type mismatch
        }
    }
    it1.forEachRemaining { onlyInList1.add(it) }
    it2.forEachRemaining { onlyInList2.add(it) }
}
Run Code Online (Sandbox Code Playgroud)

IntelliJ IDEA 2018.1.4中的Kotlin编译器(1.2.41)给出了编译时错误(如上所示).错误消息说:

Type mismatch.
Required: Comparable<Boolean>!
Found: T!
Run Code Online (Sandbox Code Playgroud)

但我并不打算if成为一个表达.我的意思是它作为一个声明(编辑:我的意思是一个表达式,其值被忽略,因为所有的ifs实际上都是表达式).如果我将其转换if为a when然后编译好了:

        when {                // <-- Look, no error! ;-)
            comp < 0 ->
                onlyInList1.add(it1.next())
            comp > 0 ->
                onlyInList2.add(it2.next())
            else -> {
                it1.next()
                it2.next()
            }
        }
Run Code Online (Sandbox Code Playgroud)

为什么它认为这if是一个表达?而且,在所有方面,为什么它认为Comparable<Boolean>!是必需的?需要这种类型的上下文在哪里?

Mar*_*nik 2

这似乎是一个编译器错误。我在这里报告了:

https://youtrack.jetbrains.net/issue/KT-24886

这是一个最小的再现器:

fun <T : Comparable<T>> test(a: Iterable<T>) {
    val x = if (booleanExpr1())
        booleanExpr2()
    else if (booleanExpr3())
        booleanExpr4()
    else {
        a.iterator().next()
    }
}

fun booleanExpr1() = true
fun booleanExpr2() = true
fun booleanExpr3() = true
fun booleanExpr4() = true
Run Code Online (Sandbox Code Playgroud)

请注意,问题根本不在于“if 表达式不被视为语句”,而在于类型推断本身。编译器应该计算出所有 then 分支的有效上限,但失败了。