[FIR] Skip redundant INAPPLICABLE_CANDIDATE on call with unresolved callable reference argument

A new resolution diagnostic UnsuccessfulCallableReferenceAtom is
introduced that is used in EagerResolveOfCallableReferences.
No diagnostic is reported on unresolved calls with this diagnostic
because

#KT-59856
This commit is contained in:
Kirill Rakhman
2023-07-18 10:16:26 +02:00
committed by Space Team
parent a55f3c5583
commit 2f3293f99e
49 changed files with 91 additions and 95 deletions
@@ -3,12 +3,12 @@ fun foo(x: String = "O"): String = x
fun bar(x: String = "K"): String = x
fun dump(dumpStrategy: String) {
val k0: kotlin.reflect.KFunction0<String> = <!INAPPLICABLE_CANDIDATE!>returnAdapter<!>(::<!UNRESOLVED_REFERENCE!>foo<!>) // Error: ADAPTED_CALLABLE_REFERENCE_AGAINST_REFLECTION_TYPE
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<!>
// Should be error here, too
val k2: kotlin.reflect.KFunction0<String> = if (dumpStrategy == "KotlinLike") ::<!UNRESOLVED_REFERENCE!>foo<!> else ::<!UNRESOLVED_REFERENCE!>bar<!>
val f0: Function0<String> = <!INAPPLICABLE_CANDIDATE!>returnAdapter<!>(::<!UNRESOLVED_REFERENCE!>foo<!>)
val f0: Function0<String> = returnAdapter(::<!UNRESOLVED_REFERENCE!>foo<!>)
val f1: Function0<String> = ::foo
val f2: Function0<String> = if (dumpStrategy == "KotlinLike") ::foo else ::bar
}
@@ -18,6 +18,6 @@ fun <K, V> B<K>.star(p: KProperty1<*, V>): B<V> = TODO()
fun <R : A> B<R>.test(){
foo(A::bla)
bar(A::bla)
<!INAPPLICABLE_CANDIDATE!>baz<!>(A::<!UNRESOLVED_REFERENCE!>bla<!>)
baz(A::<!UNRESOLVED_REFERENCE!>bla<!>)
star(A::bla)
}
@@ -14,5 +14,5 @@ fun <K, V> B<K>.foo(p: KProperty1<K, V>) {}
class C : A
fun <R : A> B<R>.test(){
<!INAPPLICABLE_CANDIDATE!>foo<!>(C::<!UNRESOLVED_REFERENCE!>bla<!>)
foo(C::<!UNRESOLVED_REFERENCE!>bla<!>)
}
@@ -7,6 +7,6 @@ fun <T> takeIt(x: T, f: SubFunction) {}
fun cr() {}
fun test() {
<!INAPPLICABLE_CANDIDATE!>takeIt<!>(42, ::<!UNRESOLVED_REFERENCE!>cr<!>)
takeIt(42, ::<!UNRESOLVED_REFERENCE!>cr<!>)
takeIt(42, <!ARGUMENT_TYPE_MISMATCH!>{ }<!>)
}
@@ -25,7 +25,7 @@ class A {
expectFunction0Unit(::foo)
expectFunction0String(::foo)
<!INAPPLICABLE_CANDIDATE!>expectFunction1Unit<!>(::<!UNRESOLVED_REFERENCE!>foo<!>)
<!INAPPLICABLE_CANDIDATE!>expectFunction1String<!>(::<!UNRESOLVED_REFERENCE!>foo<!>)
expectFunction1Unit(::<!UNRESOLVED_REFERENCE!>foo<!>)
expectFunction1String(::<!UNRESOLVED_REFERENCE!>foo<!>)
}
}
@@ -17,7 +17,7 @@ fun test2() {
fun foo() {}
<!UNRESOLVED_REFERENCE!>Unresolved<!>::foo
<!INAPPLICABLE_CANDIDATE!>foo<!>(<!UNRESOLVED_REFERENCE!>Unresolved<!>::foo)
<!INAPPLICABLE_CANDIDATE!>foo<!>(<!UNRESOLVED_REFERENCE!>Unresolved<!>::unresolved)
foo(<!UNRESOLVED_REFERENCE!>Unresolved<!>::foo)
foo(<!UNRESOLVED_REFERENCE!>Unresolved<!>::unresolved)
::<!UNRESOLVED_REFERENCE!>unresolved<!>
}
@@ -16,14 +16,14 @@ fun <T> bar(s: T) {}
fun <T> complex(t: T, f: (T) -> Unit) {}
fun test1() {
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, A::<!UNRESOLVED_REFERENCE!>invokeLater<!>) // KT-24507 SAM conversion accidentally applied to callable reference and incorrectly handled via BE
foo(1, A::<!UNRESOLVED_REFERENCE!>invokeLater<!>) // KT-24507 SAM conversion accidentally applied to callable reference and incorrectly handled via BE
foo(1, ::bar)
complex(1, ::bar)
}
fun <R> test2(x: R) {
<!INAPPLICABLE_CANDIDATE!>foo<!>(x, A::<!UNRESOLVED_REFERENCE!>invokeLater<!>) // KT-24507 SAM conversion accidentally applied to callable reference and incorrectly handled via BE
foo(x, A::<!UNRESOLVED_REFERENCE!>invokeLater<!>) // KT-24507 SAM conversion accidentally applied to callable reference and incorrectly handled via BE
foo(x, ::bar)
complex(x, ::bar)
@@ -13,7 +13,7 @@ fun <T> Wrapper<T>.baz(transform: (T) -> Unit): T = TODO()
fun test() {
takeFun<String>(::foo)
<!INAPPLICABLE_CANDIDATE!>takeFun<!><String>(::<!UNRESOLVED_REFERENCE!>fooInt<!>)
takeFun<String>(::<!UNRESOLVED_REFERENCE!>fooInt<!>)
callFun<String, Wrapper<String>>(::createWrapper)
callFun<Int, Wrapper<Number>>(::createWrapper)
@@ -22,8 +22,8 @@ fun test1() {
fun <T> test2() {
bar<Wrapper, Int, String>(Wrapper::fooReturnString).checkType { _<Tripple<Wrapper, Int, String>>() }
bar<Wrapper, T, String>(Wrapper::fooReturnString).checkType { _<Tripple<Wrapper, T, String>>() }
<!INAPPLICABLE_CANDIDATE!>bar<!><Wrapper, T, T>(Wrapper::<!UNRESOLVED_REFERENCE!>fooReturnString<!>)
<!INAPPLICABLE_CANDIDATE!>bar<!><Wrapper, Int, Int>(Wrapper::<!UNRESOLVED_REFERENCE!>fooReturnString<!>)
bar<Wrapper, T, T>(Wrapper::<!UNRESOLVED_REFERENCE!>fooReturnString<!>)
bar<Wrapper, Int, Int>(Wrapper::<!UNRESOLVED_REFERENCE!>fooReturnString<!>)
bar<Wrapper, Int, T>(Wrapper::fooTakeInt).checkType { _<Tripple<Wrapper, Int, T>>() }
bar<Wrapper, Int, String>(Wrapper::fooTakeInt).checkType { _<Tripple<Wrapper, Int, String>>() }
@@ -17,5 +17,5 @@ fun <T> bar(x: T, f: (T) -> Unit) {}
fun test2() {
bar(1, ::foo)
bar("", ::foo)
<!INAPPLICABLE_CANDIDATE!>bar<!>(1.0, ::<!UNRESOLVED_REFERENCE!>foo<!>)
bar(1.0, ::<!UNRESOLVED_REFERENCE!>foo<!>)
}
@@ -4,7 +4,7 @@ fun foo(vararg ints: Int) {}
fun test(i: IntArray) {
myLet(i, ::foo)
myLet(::foo)
<!INAPPLICABLE_CANDIDATE!>myLet<!><Int>(::<!UNRESOLVED_REFERENCE!>foo<!>)
myLet<Int>(::<!UNRESOLVED_REFERENCE!>foo<!>)
myLet<IntArray>(::foo)
myLetExplicit1(::foo)
myLetExplicit2(::foo)
@@ -1,10 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.KProperty1
class TestClass(var prop: Int)
open class OtherClass
fun OtherClass.test(prop: KProperty1<TestClass, Int>): Unit = throw Exception()
class OtherClass2: OtherClass() {
val result = <!INAPPLICABLE_CANDIDATE!>test<!>(TestClass::<!UNRESOLVED_REFERENCE!>result<!>)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.KProperty1
@@ -22,6 +22,6 @@ object Local {
fun baz(x: Int, y: Int = 0): Int = 0
fun test() {
<!INAPPLICABLE_CANDIDATE!>bar<!>(::<!UNRESOLVED_REFERENCE!>baz<!>)
bar(::<!UNRESOLVED_REFERENCE!>baz<!>)
}
}
@@ -7,4 +7,4 @@ fun foo(s: String) {}
val x1 = ofType<() -> Unit>(::foo)
val x2 = ofType<(String) -> Unit>(::foo)
val x3 = <!INAPPLICABLE_CANDIDATE!>ofType<!><(Int) -> Unit>(::<!UNRESOLVED_REFERENCE!>foo<!>)
val x3 = ofType<(Int) -> Unit>(::<!UNRESOLVED_REFERENCE!>foo<!>)
@@ -22,6 +22,6 @@ object Local {
fun baz(x: Int, y: Int = 0): Int = 0
fun test() {
<!INAPPLICABLE_CANDIDATE!>bar<!>(::<!UNRESOLVED_REFERENCE!>baz<!>)
bar(::<!UNRESOLVED_REFERENCE!>baz<!>)
}
}
@@ -5,4 +5,4 @@ import kotlin.reflect.KProperty0
object A
fun <TProperty> property0(property: KProperty0<TProperty>) = A
val <K> K.key get() : A = <!INAPPLICABLE_CANDIDATE!>property0<!>(Map.Entry<K, *>::<!UNRESOLVED_REFERENCE!>key<!>) // should be forbidden
val <K> K.key get() : A = property0(Map.Entry<K, *>::<!UNRESOLVED_REFERENCE!>key<!>) // should be forbidden
@@ -10,6 +10,6 @@ fun <T> baz(e: T, f: (T) -> Unit) {}
fun test(a: A, b: B) {
// Note that diagnostic is always on callable references as they are resolved after simple arguments
<!INAPPLICABLE_CANDIDATE!>baz<!>(a, ::<!UNRESOLVED_REFERENCE!>fooB<!>)
<!INAPPLICABLE_CANDIDATE!>bar<!>(::<!UNRESOLVED_REFERENCE!>fooB<!>, a)
baz(a, ::<!UNRESOLVED_REFERENCE!>fooB<!>)
bar(::<!UNRESOLVED_REFERENCE!>fooB<!>, a)
}
@@ -8,4 +8,4 @@ fun foo(s: String) {}
val x1 = apply(1, ::foo)
val x2 = apply("hello", ::foo)
val x3 = <!INAPPLICABLE_CANDIDATE!>apply<!>(true, ::<!UNRESOLVED_REFERENCE!>foo<!>)
val x3 = apply(true, ::<!UNRESOLVED_REFERENCE!>foo<!>)
@@ -3,7 +3,7 @@
fun a() {
val x = 10
<!INAPPLICABLE_CANDIDATE!>foo<!>(::<!UNSUPPORTED!>x<!>)
foo(::<!UNSUPPORTED!>x<!>)
}
fun foo(a: Any) {}
@@ -11,5 +11,5 @@ fun test(param: String) {
val lambda = { -> }
val g = ::<!UNSUPPORTED!>lambda<!>
<!INAPPLICABLE_CANDIDATE!>eat<!>(::<!UNSUPPORTED!>param<!>)
eat(::<!UNSUPPORTED!>param<!>)
}
@@ -9,6 +9,6 @@ class Foo {
fun main() {
val f = Foo()
val a: Int
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = f.<!INAPPLICABLE_CANDIDATE!>getValue<!>(null, ::<!UNSUPPORTED!>a<!>) // no exception after fix
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = f.getValue(null, ::<!UNSUPPORTED!>a<!>) // no exception after fix
<!UNRESOLVED_REFERENCE!>print<!>(<!UNINITIALIZED_VARIABLE!>a<!>)
}
@@ -9,6 +9,6 @@ class Foo {
fun main(x: Int) {
val f = Foo()
val a: Int
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = f.<!INAPPLICABLE_CANDIDATE!>getValue<!>(null, ::<!UNSUPPORTED!>x<!>) // no exception after fix
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = f.getValue(null, ::<!UNSUPPORTED!>x<!>) // no exception after fix
<!UNRESOLVED_REFERENCE!>print<!>(<!UNINITIALIZED_VARIABLE!>a<!>)
}