[FIR] If callable reference can't be resolved with expected type, try resolving with Any

In positions outside of calls (e.g. property initializers)
we resolve callable references using a synthetic outer call with the
expected type as parameter type.
If this fails, we previously returned an unresolved reference.
After this commit, we additionally try to resolve the callable reference
with expected type Any.
This lets us report more precise diagnostics like type mismatches or
when multiple overloads exist NONE_APPLICABLE.

#KT-55373 Fixed
#KT-55955 Fixed
This commit is contained in:
Kirill Rakhman
2023-07-27 18:32:16 +02:00
committed by Space Team
parent 2c91ae1129
commit ade1354a84
20 changed files with 143 additions and 79 deletions
@@ -4,9 +4,9 @@ fun bar(x: String = "K"): String = x
fun dump(dumpStrategy: String) {
val k0: kotlin.reflect.KFunction0<String> = returnAdapter(::<!UNRESOLVED_REFERENCE!>foo<!>) // Error: ADAPTED_CALLABLE_REFERENCE_AGAINST_REFLECTION_TYPE
val k1: kotlin.reflect.KFunction0<String> = ::<!UNRESOLVED_REFERENCE!>foo<!>
val k1: kotlin.reflect.KFunction0<String> = <!INITIALIZER_TYPE_MISMATCH!>::foo<!>
// Should be error here, too
val k2: kotlin.reflect.KFunction0<String> = if (dumpStrategy == "KotlinLike") ::<!UNRESOLVED_REFERENCE!>foo<!> else ::<!UNRESOLVED_REFERENCE!>bar<!>
val k2: kotlin.reflect.KFunction0<String> = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>if (dumpStrategy == "KotlinLike") ::foo else ::bar<!>
val f0: Function0<String> = returnAdapter(::<!UNRESOLVED_REFERENCE!>foo<!>)
val f1: Function0<String> = ::foo
@@ -22,6 +22,6 @@ class A3<T> {
fun test2(): (T) -> Unit = A3<T>()::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>a3<!>
fun test3(): (Int) -> String = A3<Int>()::a3
fun <R> test4(): (R) -> Unit = this::<!UNRESOLVED_REFERENCE!>a3<!>
fun <R> test4(): (R) -> Unit = <!RETURN_TYPE_MISMATCH!>this::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>a3<!><!>
fun <R> test5(): (T) -> R = this::a3
}
@@ -0,0 +1,7 @@
class One
fun one() = Unit
class Two
val test: Two = <!INITIALIZER_TYPE_MISMATCH!>::One<!>
val test2: Two = <!INITIALIZER_TYPE_MISMATCH!>::one<!>
val test3: (String) -> One = <!INITIALIZER_TYPE_MISMATCH!>::One<!>
@@ -0,0 +1,7 @@
class One
fun one() = Unit
class Two
val test: Two = <!TYPE_MISMATCH!>::<!TYPE_MISMATCH!>One<!><!>
val test2: Two = <!TYPE_MISMATCH!>::<!TYPE_MISMATCH!>one<!><!>
val test3: (String) -> One = <!TYPE_MISMATCH!>::<!TYPE_MISMATCH!>One<!><!>
@@ -1,9 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo() {}
fun foo(s: String) {}
val x1 = ::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>
val x2: () -> Unit = ::foo
val x3: (String) -> Unit = ::foo
val x4: (Int) -> Unit = ::<!UNRESOLVED_REFERENCE!>foo<!>
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo() {}
@@ -1,21 +0,0 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
interface IA
interface IB : IA
fun IA.extFun(x: IB) {}
fun IB.extFun(x: IA) {}
fun test() {
val extFun1 = IA::extFun
val extFun2 = IB::<!OVERLOAD_RESOLUTION_AMBIGUITY!>extFun<!>
}
fun testWithExpectedType() {
val extFun_AB_A: IA.(IB) -> Unit = IA::extFun
val extFun_AA_B: IA.(IA) -> Unit = IB::<!UNRESOLVED_REFERENCE!>extFun<!>
val extFun_BB_A: IB.(IB) -> Unit = IA::extFun
val extFun_BA_B: IB.(IA) -> Unit = IB::extFun
val extFun_BB_B: IB.(IB) -> Unit = IB::<!OVERLOAD_RESOLUTION_AMBIGUITY!>extFun<!>
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE