[FIR] Fixes for call conflict resolution

Let ConeCompositeConflictResolver pass the results of the previous
resolver to the next one.
Otherwise, we get false positive conflicts when a set of candidates
can't be fully reduced by one resolver but could be resolved by the
subsequent application of multiple ones.
This change makes ConeCompositeConflictResolver order-dependent and
thus, ConeOverloadConflictResolver must be invoked last, because it
must work on a pre-filtered list.

Also, let ConeEquivalentCallConflictResolver use
FirStandardOverrideChecker instead of compareCallsByUsedArguments
because it's stricter.

This all fixes a false positive overload resolution ambiguity in common
metadata compilation that is caused by stdlib using the new KMP
format.
Now stdlib metadata is in the classpath, and so declarations from the
stdlib are returned from both MetadataSymbolProvider and
KlibBasedSymbolProvider.
This isn't a problem per se because duplicate candidates are filtered
out by ConeEquivalentCallConflictResolver (K1 works analogously), but
in the case of top-level functions with generic receivers like
Collection<T>.toTypedArray, the check failed because of the direct
comparison of receiver types.

#KT-60943 Fixed
This commit is contained in:
Kirill Rakhman
2023-08-10 12:45:09 +02:00
committed by Space Team
parent 86ef313233
commit 724d527fd8
19 changed files with 55 additions and 167 deletions
@@ -36,7 +36,7 @@ fun case1() {
val a: Boolean? = false
checkSubtype<Boolean?>(a)
val x4 = <!CONDITION_TYPE_MISMATCH!>a<!> && true
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
x4 checkType { check<Boolean>() }
}
// TESTCASE NUMBER: 2
@@ -44,7 +44,7 @@ fun case2() {
val a: Any = false
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>a<!>
val x4 = <!CONDITION_TYPE_MISMATCH!>a<!> && true
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
x4 checkType { check<Boolean>() }
}
// TESTCASE NUMBER: 3
@@ -56,7 +56,7 @@ fun case3() {
val x3 = a1 && <!CONDITION_TYPE_MISMATCH!>a2<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>x3<!>
x3 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
x3 checkType { check<Boolean>() }
}
// TESTCASE NUMBER: 4
@@ -1,56 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION
// SKIP_TXT
/*
* KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE)
*
* SPEC VERSION: 0.1-313
* MAIN LINK: expressions, logical-conjunction-expression -> paragraph 2 -> sentence 1
* PRIMARY LINKS: expressions, logical-conjunction-expression -> paragraph 2 -> sentence 2
* NUMBER: 1
* DESCRIPTION: Both operands of a logical conjunction expression must have a type which is a subtype of kotlin.Boolean
* HELPERS: checkType
*/
// MODULE: libModule
// FILE: libModule/JavaClass.java
package libModule;
public class JavaClass {
public static boolean VALUE;
public static Object VALUE_OBJ = true;
public Boolean getValue ()
{ return new Boolean ("true"); }
}
// MODULE: mainModule(libModule)
// FILE: KotlinClass.kt
package mainModule
import libModule.*
import checkSubtype
import checkType
import check
fun foo() = run { false && JavaClass.VALUE && throw Exception() }
// TESTCASE NUMBER: 1
fun case1() {
val a1 = false
val a2 = JavaClass.VALUE
val a3 = foo()
val a4 = JavaClass().getValue()
val a5 = JavaClass.VALUE_OBJ
checkSubtype<Boolean>(a1)
checkSubtype<Boolean>(a2)
checkSubtype<Boolean>(a3)
checkSubtype<Boolean>(a4)
val x3 = a1 && a2 && a3 && a4 && a5 as Boolean
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>x3<!>
x3 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>()}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION
// SKIP_TXT
@@ -36,7 +36,7 @@ fun case1() {
val a: Boolean? = false
checkSubtype<Boolean?>(a)
val x4 = <!CONDITION_TYPE_MISMATCH!>a<!> || true
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
x4 checkType { check<Boolean>() }
}
// TESTCASE NUMBER: 2
@@ -44,7 +44,7 @@ fun case2() {
val a: Any = false
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>a<!>
val x4 = <!CONDITION_TYPE_MISMATCH!>a<!> || true
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
x4 checkType { check<Boolean>() }
}
// TESTCASE NUMBER: 3
@@ -56,7 +56,7 @@ fun case3() {
val x3 = a1 || <!CONDITION_TYPE_MISMATCH!>a2<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>x3<!>
x3 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
x3 checkType { check<Boolean>() }
}
// TESTCASE NUMBER: 4
@@ -1,56 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION
// SKIP_TXT
/*
* KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE)
*
* SPEC VERSION: 0.1-313
* MAIN LINK: expressions, logical-disjunction-expression -> paragraph 2 -> sentence 1
* PRIMARY LINKS: expressions, logical-disjunction-expression -> paragraph 2 -> sentence 2
* NUMBER: 1
* DESCRIPTION:Both operands of a logical disjunction expression must have a type which is a subtype of kotlin.Boolean
* HELPERS: checkType
*/
// MODULE: libModule
// FILE: libModule/JavaClass.java
package libModule;
public class JavaClass {
public static boolean VALUE;
public static Object VALUE_OBJ = true;
public Boolean getValue ()
{ return new Boolean ("true"); }
}
// MODULE: mainModule(libModule)
// FILE: KotlinClass.kt
package mainModule
import libModule.*
import checkSubtype
import checkType
import check
fun foo() = run { false || JavaClass.VALUE || throw Exception() }
// TESTCASE NUMBER: 1
fun case1() {
val a1 = false
val a2 = JavaClass.VALUE
val a3 = foo()
val a4 = JavaClass().getValue()
val a5 = JavaClass.VALUE_OBJ
checkSubtype<Boolean>(a1)
checkSubtype<Boolean>(a2)
checkSubtype<Boolean>(a3)
checkSubtype<Boolean>(a4)
val x3 = a1 || a2 || a3 || a4 || a5 as Boolean
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>x3<!>
x3 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>()}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION
// SKIP_TXT