[FIR] Improve diagnostic reporting & don't use error symbol for candidate if possible

Also introduce few new diagnostics:
- NONE_APPLICABLE more many inapplicable candidates
- HIDDEN for visible candidates
This commit is contained in:
Dmitriy Novozhilov
2020-07-22 16:40:14 +03:00
committed by Mikhail Glukhikh
parent 5c0528b61e
commit f283f2db43
365 changed files with 1400 additions and 1451 deletions
@@ -74,20 +74,20 @@ class Derived : Base() {
class Other {
fun test(base: Base, derived: Derived) {
base.<!INAPPLICABLE_CANDIDATE!>foo<!>()
base.<!HIDDEN!>foo<!>()
base.<!UNRESOLVED_REFERENCE!>gav<!>()
base.<!UNRESOLVED_REFERENCE!>bar<!>()
derived.<!INAPPLICABLE_CANDIDATE!>foo<!>()
derived.<!HIDDEN!>foo<!>()
derived.<!UNRESOLVED_REFERENCE!>gav<!>()
derived.<!UNRESOLVED_REFERENCE!>bar<!>()
}
}
fun top(base: Base, derived: Derived) {
base.<!INAPPLICABLE_CANDIDATE!>foo<!>()
base.<!HIDDEN!>foo<!>()
base.<!UNRESOLVED_REFERENCE!>bar<!>()
base.<!UNRESOLVED_REFERENCE!>gav<!>()
derived.<!INAPPLICABLE_CANDIDATE!>foo<!>()
derived.<!HIDDEN!>foo<!>()
derived.<!UNRESOLVED_REFERENCE!>bar<!>()
derived.<!UNRESOLVED_REFERENCE!>gav<!>()
}
@@ -20,7 +20,7 @@ class SomeClass {
}
fun callMemberContractWithoutThis() {
<!INAPPLICABLE_CANDIDATE!>contract<!>()
<!NONE_APPLICABLE!>contract<!>()
}
fun callTopLevelSamePsiInMember() {
@@ -8,6 +8,6 @@ class Scope<InterfaceT, ImplementationT : InterfaceT>(private val implClass: j.C
val hm = c.asSequence()
.<!INAPPLICABLE_CANDIDATE!>filter<!>(<!UNRESOLVED_REFERENCE!>implClass::isInstance<!>)
.<!INAPPLICABLE_CANDIDATE!>map<!>(<!UNRESOLVED_REFERENCE!>implClass::cast<!>)
.<!AMBIGUITY!>toSet<!>()
.toSet()
}
}
@@ -11,7 +11,7 @@ suspend fun String.id(): String = this
fun box() {
val x = "f"
builder {
<!INAPPLICABLE_CANDIDATE!>go1<!>(x::id)
<!INAPPLICABLE_CANDIDATE!>go2<!>(x::id)
<!INAPPLICABLE_CANDIDATE!>go1<!>(<!UNRESOLVED_REFERENCE!>x::id<!>)
<!INAPPLICABLE_CANDIDATE!>go2<!>(<!UNRESOLVED_REFERENCE!>x::id<!>)
}
}
@@ -15,8 +15,8 @@ suspend fun bar(x: Int) {}
fun test() {
test0(::foo)
<!INAPPLICABLE_CANDIDATE!>test1<!>(::foo)
<!INAPPLICABLE_CANDIDATE!>test1<!>(<!UNRESOLVED_REFERENCE!>::foo<!>)
<!INAPPLICABLE_CANDIDATE!>test0<!>(::bar)
<!INAPPLICABLE_CANDIDATE!>test0<!>(<!UNRESOLVED_REFERENCE!>::bar<!>)
test1(::bar)
}
}
@@ -11,14 +11,14 @@ fun <E> myBuildList(@BuilderInference builderAction: MutableList<E>.() -> Unit)
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val newList1 = myBuildList {
<!INAPPLICABLE_CANDIDATE!>addAll<!>(
addAll(
listOf(1).map { <!INAPPLICABLE_CANDIDATE!>Foo<!>(null) }
)
}
val newList2 = buildList {
<!INAPPLICABLE_CANDIDATE!>addAll<!>(listOf(1,2,3).map{ <!INAPPLICABLE_CANDIDATE!>Foo<!>(null) })
addAll(listOf(1,2,3).map{ <!INAPPLICABLE_CANDIDATE!>Foo<!>(null) })
}
}
class Foo(val notNullProp: String)
class Foo(val notNullProp: String)
@@ -22,7 +22,7 @@ fun test() {
builder {
noParams()
yieldString("abc") checkType { _<Unit>() }
<!INAPPLICABLE_CANDIDATE!>yieldString<!>(1) <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Unit>() }
<!INAPPLICABLE_CANDIDATE!>yieldString<!>(1) checkType { _<Unit>() }
await<String> { "123" } checkType { _<String>() }
@@ -36,7 +36,7 @@ fun test() {
severalParams("", 89) checkType { _<Double>() }
// TODO: should we allow somehow to call with passing continuation explicitly?
<!INAPPLICABLE_CANDIDATE!>severalParams<!>("", 89, 6.9) <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Unit>() }
<!INAPPLICABLE_CANDIDATE!>severalParams<!>("", 89, 6.9) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Unit>() }
"".stringReceiver(1)
Any().anyReceiver(1)
@@ -23,7 +23,7 @@ fun test() {
builder {
noParams()
yieldString("abc") checkType { _<Unit>() }
<!INAPPLICABLE_CANDIDATE!>yieldString<!>(1) <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Unit>() }
<!INAPPLICABLE_CANDIDATE!>yieldString<!>(1) checkType { _<Unit>() }
await<String> { "123" } checkType { _<String>() }
@@ -38,7 +38,7 @@ fun test() {
severalParams("", 89) checkType { _<Double>() }
// TODO: should we allow somehow to call with passing continuation explicitly?
<!INAPPLICABLE_CANDIDATE!>severalParams<!>("", 89, 6.9) <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Unit>() }
<!INAPPLICABLE_CANDIDATE!>severalParams<!>("", 89, this as Continuation<Double>) <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Unit>() }
<!INAPPLICABLE_CANDIDATE!>severalParams<!>("", 89, 6.9) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Unit>() }
<!INAPPLICABLE_CANDIDATE!>severalParams<!>("", 89, this as Continuation<Double>) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Unit>() }
}
}
@@ -28,8 +28,8 @@ fun <T, R> Iterable<T>.fooMap(t: (T) -> Sequence<R>): List<R> {
}
fun test() {
val list = ubyteArrayOf(0u).<!AMBIGUITY!>fooMap<!> { <!INAPPLICABLE_CANDIDATE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>) }
val list = ubyteArrayOf(0u).<!AMBIGUITY!>fooMap<!> { <!NONE_APPLICABLE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>) }
takeUByteList(list)
}
fun takeUByteList(list: List<UByte>) {}
fun takeUByteList(list: List<UByte>) {}
@@ -21,5 +21,5 @@ fun main() {
// Here, the error should be
val x2: (Int) -> Unit = takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> & kotlin.Function1<kotlin.Int, kotlin.Unit>")!>id { <!UNRESOLVED_REFERENCE!>it<!> }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Nothing>")!>{ x -> x }<!>)
val x3: suspend (Int) -> Unit = takeSimpleFunction(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Unit> & kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>id { <!UNRESOLVED_REFERENCE!>it<!> }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Nothing>")!>{ x -> x }<!>)
val x4: (Int) -> Unit = <!INAPPLICABLE_CANDIDATE!>takeSimpleFunction<!>(id<suspend (Int) -> Unit> {}, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function0<kotlin.Unit>")!>{}<!>)
val x4: (Int) -> Unit = <!INAPPLICABLE_CANDIDATE!>takeSimpleFunction<!>(id<suspend (Int) -> Unit> {}, <!DEBUG_INFO_EXPRESSION_TYPE("Type is unknown")!>{}<!>)
}
@@ -1,4 +1,4 @@
// !WITH_NEW_INFERENCE
// NI_EXPECTED_FILE
fun foo(first: Array<Any?>, second: Array<Any?>) = <!INAPPLICABLE_CANDIDATE!>Pair<!>(first.<!INAPPLICABLE_CANDIDATE!>toCollection<!>(), second.<!INAPPLICABLE_CANDIDATE!>toCollection<!>())
fun foo(first: Array<Any?>, second: Array<Any?>) = Pair(first.<!INAPPLICABLE_CANDIDATE!>toCollection<!>(), second.<!INAPPLICABLE_CANDIDATE!>toCollection<!>())
@@ -20,7 +20,7 @@ fun testArrays(ci: List<Int?>, cii: List<Int?>?) {
checkSubtype<Array<Int?>>(c1)
checkSubtype<Array<Int?>>(c2)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Array<Int?>>(c3)
checkSubtype<Array<Int?>>(c3)
checkSubtype<Array<Int?>>(c4)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Array<Int?>>(c5)
checkSubtype<Array<Int?>>(c5)
}
@@ -24,7 +24,7 @@ public class StaticOverrides {
// FILE: test.kt
fun test() {
StaticOverrides.A.<!AMBIGUITY!>foo<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Boolean>() }
StaticOverrides.A.<!AMBIGUITY!>foo<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Boolean>() }
StaticOverrides.B.foo {} checkType { _<String>() }
StaticOverrides.C.<!AMBIGUITY!>foo<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Boolean>() }
StaticOverrides.C.<!AMBIGUITY!>foo<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Boolean>() }
}
@@ -20,6 +20,6 @@ class Foo {
// FILE: 1.kt
fun test() {
Foo().<!AMBIGUITY!>foo<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
Foo().<!AMBIGUITY!>bar<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
}
Foo().<!AMBIGUITY!>foo<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
Foo().<!AMBIGUITY!>bar<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
}
@@ -21,6 +21,6 @@ class Foo {
// FILE: 1.kt
fun test() {
Foo().<!AMBIGUITY!>foo<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
Foo().<!AMBIGUITY!>bar<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
}
Foo().<!AMBIGUITY!>foo<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
Foo().<!AMBIGUITY!>bar<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
}
@@ -16,5 +16,5 @@ public class Foo {
// FILE: 1.kt
fun bar() {
Foo().<!AMBIGUITY!>test<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
}
Foo().<!AMBIGUITY!>test<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
}
@@ -18,5 +18,5 @@ public class Foo {
// FILE: 1.kt
fun bar() {
Foo().<!AMBIGUITY!>test<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
}
Foo().<!AMBIGUITY!>test<!> {} <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
}
@@ -3,7 +3,7 @@
fun indexOfMax(a: IntArray): Int? {
var maxI: Int? = 0
a.forEachIndexed { i, value ->
if (value <!AMBIGUITY!>>=<!> <!INAPPLICABLE_CANDIDATE!>a[maxI]<!>) {
if (value >= <!INAPPLICABLE_CANDIDATE!>a[maxI]<!>) {
maxI = i
}
else if (value < 0) {
@@ -28,7 +28,7 @@ interface A2 : List<String> {
override fun stream(): java.util.stream.Stream<String> = null!!
}
class B : <!INAPPLICABLE_CANDIDATE!>Throwable<!>("", null, false, false)
class B : <!NONE_APPLICABLE!>Throwable<!>("", null, false, false)
class B1 : RuntimeException() {
override fun fillInStackTrace(): Throwable { // 'override' keyword must be prohibited, as it was in 1.0.x
@@ -23,5 +23,5 @@ typealias C2<T> = JHost.Consumer2<T, T>
val test1 = R { }
val test2 = C<String> { s -> println(s.length) }
val test3 = CStr { s -> <!AMBIGUITY!>println<!>(s.<!UNRESOLVED_REFERENCE!>length<!>) }
val test4 = CStrList { ss -> <!INAPPLICABLE_CANDIDATE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (s in ss) { <!AMBIGUITY!>println<!>(s.<!UNRESOLVED_REFERENCE!>length<!>) }<!> }
val test4 = CStrList { ss -> <!NONE_APPLICABLE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (s in ss) { <!AMBIGUITY!>println<!>(s.<!UNRESOLVED_REFERENCE!>length<!>) }<!> }
val test5 = <!INAPPLICABLE_CANDIDATE!>C2<!><Int> { a, b -> val x: Int = a <!AMBIGUITY!>+<!> b; println(x)}
@@ -24,20 +24,20 @@ val test3: MutableList<Int> =
val test4: Collection<Int> =
listOf(1, 2, 3).<!AMBIGUITY!>flatMapTo<!>(LinkedHashSet()) {
<!INAPPLICABLE_CANDIDATE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>)
<!NONE_APPLICABLE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>)
}
val test5: Collection<Int> =
listOf(1, 2, 3).<!AMBIGUITY!>flatMapTo<!>(LinkedHashSet()) { // TODO
if (true) <!INAPPLICABLE_CANDIDATE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>) else <!INAPPLICABLE_CANDIDATE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>)
if (true) <!NONE_APPLICABLE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>) else <!NONE_APPLICABLE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>)
}
val test6: Collection<Int> =
listOf(1, 2, 3).<!AMBIGUITY!>flatMapTo<!>(LinkedHashSet<Int>()) {
if (true) <!INAPPLICABLE_CANDIDATE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>) else <!INAPPLICABLE_CANDIDATE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>)
if (true) <!NONE_APPLICABLE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>) else <!NONE_APPLICABLE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>)
}
val test7: Collection<Int> =
listOf(1, 2, 3).<!AMBIGUITY!>flatMapTo<!>(LinkedHashSet()) {
<!INAPPLICABLE_CANDIDATE!>select<!>(<!INAPPLICABLE_CANDIDATE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>), <!INAPPLICABLE_CANDIDATE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>))
}
<!INAPPLICABLE_CANDIDATE!>select<!>(<!NONE_APPLICABLE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>), <!NONE_APPLICABLE!>listOf<!>(<!UNRESOLVED_REFERENCE!>it<!>))
}