[NI] Remove lambda coersion to Unit in case of error return type(s)

Coersion to Unit from error type leads to misleading type mismatches:
"expected <expected lambda return type> found Unit", despite no user-provided Unit / empty lambda.
These diagnostics were collected, but not reported before, and that had been disguising the issue for a while.

KT-34729 Fixed
This commit is contained in:
Pavel Kirpichenkov
2020-01-20 19:25:35 +03:00
parent 3a98c84105
commit c5893913f3
39 changed files with 263 additions and 46 deletions
@@ -0,0 +1,74 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !WITH_NEW_INFERENCE
fun takeFnToAny(fn: () -> Any) {}
fun takeFnToUnit(fn: () -> Unit) {}
fun <P> takeFnToParameter(fn: () -> P) {}
fun testAny() {
takeFnToAny { }
takeFnToAny { Unit }
takeFnToAny { <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToAny { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToAny { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() else <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToAny(fun() = Unit)
takeFnToAny(fun() {})
takeFnToAny(fun() { return })
takeFnToAny(fun() { return Unit })
takeFnToAny(fun(): Unit {})
takeFnToAny(fun(): Unit { return })
takeFnToAny(fun(): Unit { return Unit })
takeFnToAny(fun() { if (true) return })
takeFnToAny(fun() { if (true) return Unit })
takeFnToAny(fun() = <!UNRESOLVED_REFERENCE!>unresolved<!>())
takeFnToAny(fun() { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToAny(fun(): Unit { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToAny(fun() { return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToAny(fun() { if (true ) return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
}
fun testUnit() {
takeFnToUnit { }
takeFnToUnit { Unit }
takeFnToUnit { <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToUnit { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToUnit { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() else <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToUnit(fun() = Unit)
takeFnToUnit(fun() {})
takeFnToUnit(fun() { return })
takeFnToUnit(fun() { return Unit })
takeFnToUnit(fun(): Unit {})
takeFnToUnit(fun(): Unit { return })
takeFnToUnit(fun(): Unit { return Unit })
takeFnToUnit(fun() { if (true) return })
takeFnToUnit(fun() { if (true) return Unit })
takeFnToUnit(fun() = <!UNRESOLVED_REFERENCE!>unresolved<!>())
takeFnToUnit(fun() { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToUnit(fun(): Unit { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToUnit(fun() { return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToUnit(fun() { if (true ) return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
}
fun testParameter() {
takeFnToParameter { }
takeFnToParameter { Unit }
takeFnToParameter { <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToParameter { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToParameter {
if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() else <!UNRESOLVED_REFERENCE!>unresolved<!>()
}
takeFnToParameter(fun() = Unit)
takeFnToParameter(fun() {})
takeFnToParameter(fun() { return })
takeFnToParameter(fun() { return Unit })
takeFnToParameter(fun(): Unit {})
takeFnToParameter(fun(): Unit { return })
takeFnToParameter(fun(): Unit { return Unit })
takeFnToParameter(fun() { if (true) return })
takeFnToParameter(fun() { if (true) return Unit })
takeFnToParameter(fun() = <!UNRESOLVED_REFERENCE!>unresolved<!>())
takeFnToParameter(fun() { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToParameter(fun(): Unit { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToParameter(fun() { return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToParameter(fun() { if (true ) return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
}
@@ -0,0 +1,74 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !WITH_NEW_INFERENCE
fun takeFnToAny(fn: () -> Any) {}
fun takeFnToUnit(fn: () -> Unit) {}
fun <P> takeFnToParameter(fn: () -> P) {}
fun testAny() {
takeFnToAny { }
takeFnToAny { Unit }
takeFnToAny { <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToAny { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToAny { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() else <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToAny(fun() = Unit)
takeFnToAny(fun() {})
takeFnToAny(fun() { return })
takeFnToAny(fun() { return Unit })
takeFnToAny(fun(): Unit {})
takeFnToAny(fun(): Unit { return })
takeFnToAny(fun(): Unit { return Unit })
takeFnToAny(fun() { if (true) return })
takeFnToAny(fun() { if (true) return Unit })
takeFnToAny(fun() = <!UNRESOLVED_REFERENCE!>unresolved<!>())
takeFnToAny(fun() { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToAny(fun(): Unit { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToAny(fun() { return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToAny(fun() { if (true ) return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
}
fun testUnit() {
takeFnToUnit { }
takeFnToUnit { Unit }
takeFnToUnit { <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToUnit { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToUnit { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() else <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToUnit(fun() = Unit)
takeFnToUnit(fun() {})
takeFnToUnit(fun() { return })
takeFnToUnit(fun() { return Unit })
takeFnToUnit(fun(): Unit {})
takeFnToUnit(fun(): Unit { return })
takeFnToUnit(fun(): Unit { return Unit })
takeFnToUnit(fun() { if (true) return })
takeFnToUnit(fun() { if (true) return Unit })
takeFnToUnit(fun() = <!UNRESOLVED_REFERENCE!>unresolved<!>())
takeFnToUnit(fun() { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToUnit(fun(): Unit { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToUnit(fun() { return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToUnit(fun() { if (true ) return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
}
fun testParameter() {
takeFnToParameter { }
takeFnToParameter { Unit }
<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeFnToParameter<!> { <!UNRESOLVED_REFERENCE!>unresolved<!>() }
takeFnToParameter { if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() }
<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeFnToParameter<!> {
if (true) <!UNRESOLVED_REFERENCE!>unresolved<!>() else <!UNRESOLVED_REFERENCE!>unresolved<!>()
}
takeFnToParameter(fun() = Unit)
takeFnToParameter(fun() {})
takeFnToParameter(fun() { return })
takeFnToParameter(fun() { return Unit })
takeFnToParameter(fun(): Unit {})
takeFnToParameter(fun(): Unit { return })
takeFnToParameter(fun(): Unit { return Unit })
takeFnToParameter(fun() { if (true) return })
takeFnToParameter(fun() { if (true) return Unit })
<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeFnToParameter<!>(fun() = <!UNRESOLVED_REFERENCE!>unresolved<!>())
takeFnToParameter(fun() { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToParameter(fun(): Unit { <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToParameter(fun() { return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
takeFnToParameter(fun() { if (true ) return <!UNRESOLVED_REFERENCE!>unresolved<!>() })
}
@@ -0,0 +1,8 @@
package
public fun takeFnToAny(/*0*/ fn: () -> kotlin.Any): kotlin.Unit
public fun </*0*/ P> takeFnToParameter(/*0*/ fn: () -> P): kotlin.Unit
public fun takeFnToUnit(/*0*/ fn: () -> kotlin.Unit): kotlin.Unit
public fun testAny(): kotlin.Unit
public fun testParameter(): kotlin.Unit
public fun testUnit(): kotlin.Unit
+1 -1
View File
@@ -2,7 +2,7 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// Related issue: KT-28654
fun <K> select(): K = <!NI;TYPE_MISMATCH, OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>run { <!OI;TYPE_MISMATCH!><!>}<!>
fun <K> select(): K = <!NI;TYPE_MISMATCH, OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>run <!NI;TYPE_MISMATCH!>{ <!OI;TYPE_MISMATCH!><!>}<!><!>
fun test() {
val x: Int = select()
@@ -13,7 +13,7 @@ fun insideJob1() = doTheJob1()
suspend fun insideJob2() = doTheJob2()
suspend fun insideJob3() = doTheJob3()
fun doTheJob0() = simpleAsync0 { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!DEBUG_INFO_MISSING_UNRESOLVED!>insideJob0<!>()<!> }
fun doTheJob1() = simpleAsync1 { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!DEBUG_INFO_MISSING_UNRESOLVED!>insideJob1<!>()<!> }
suspend fun doTheJob2() = simpleAsync2 { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!DEBUG_INFO_MISSING_UNRESOLVED!>insideJob2<!>()<!> }
suspend fun doTheJob3() = simpleAsync3 { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!DEBUG_INFO_MISSING_UNRESOLVED!>insideJob3<!>()<!> }
fun doTheJob0() = <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>simpleAsync0<!> { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!DEBUG_INFO_MISSING_UNRESOLVED!>insideJob0<!>()<!> }
fun doTheJob1() = <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>simpleAsync1<!> { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!DEBUG_INFO_MISSING_UNRESOLVED!>insideJob1<!>()<!> }
suspend fun doTheJob2() = <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>simpleAsync2<!> { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!DEBUG_INFO_MISSING_UNRESOLVED!>insideJob2<!>()<!> }
suspend fun doTheJob3() = <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>simpleAsync3<!> { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!DEBUG_INFO_MISSING_UNRESOLVED!>insideJob3<!>()<!> }
@@ -1,4 +1,6 @@
//KT-2741 Compiler can't infer a type of a function literal parameter when its body contains errors
// !WITH_NEW_INFERENCE
package a
fun <T, R: Comparable<R>> Iterable<T>._sortBy(f: (T) -> R): List<T> = throw Exception()
@@ -1,4 +1,6 @@
//KT-2741 Compiler can't infer a type of a function literal parameter when its body contains errors
// !WITH_NEW_INFERENCE
package a
fun <T, R: Comparable<R>> Iterable<T>._sortBy(<!UNUSED_PARAMETER!>f<!>: (T) -> R): List<T> = throw Exception()
@@ -7,5 +9,5 @@ fun <T> _arrayList(vararg <!UNUSED_PARAMETER!>values<!>: T) : List<T> = throw Ex
class _Pair<A>(val a: A)
fun test() {
_arrayList(_Pair(1))._sortBy { <!UNUSED_ANONYMOUS_PARAMETER!>it<!> -> <!UNRESOLVED_REFERENCE!>xxx<!> }
_arrayList(_Pair(1)).<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>_sortBy<!> { <!UNUSED_ANONYMOUS_PARAMETER!>it<!> -> <!UNRESOLVED_REFERENCE!>xxx<!> }
}
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {}
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {}
@@ -8,7 +10,7 @@ public inline fun <T: Closeable, R> T.use1(block: (T)-> R) : R {
}
fun main() {
C().use1 {
C().<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>use1<!> {
<!UNUSED_ANONYMOUS_PARAMETER!>w<!> -> // ERROR here
<!UNRESOLVED_REFERENCE!>x<!>
}
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {
@@ -11,7 +13,7 @@ public inline fun <T: Closeable, R> T.use(block: (t: T)-> R) : R {
}
fun test() {
C().use {
C().<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>use<!> {
it.close()
<!UNRESOLVED_REFERENCE!>x<!>
}
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {
@@ -11,7 +13,7 @@ public inline fun <T: Closeable, R> use(t: T, block: T.(T)-> R) : R {
}
fun test() {
use(C()) {
<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>use<!>(C()) {
this.close()
it.close()
<!UNRESOLVED_REFERENCE!>xx<!>
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {
@@ -11,7 +13,7 @@ public inline fun <T: Closeable, R> T.use(block: T.()-> R) : R {
}
fun test() {
C().use {
C().<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>use<!> {
this.close()
<!UNRESOLVED_REFERENCE!>x<!>
}
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {}
@@ -1,3 +1,5 @@
// !WITH_NEW_INFERENCE
package a
interface Closeable {}
@@ -8,7 +10,7 @@ fun <T: Closeable, R> T.foo(block: (T)-> R) = block
fun <T: Closeable, R> T.foo(block: (T, T)-> R) = block
fun main() {
C().foo { // no ambiguity here
C().<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!> { // no ambiguity here
<!UNUSED_ANONYMOUS_PARAMETER!>www<!> ->
<!UNRESOLVED_REFERENCE!>xs<!>
}