Fix KT-10472: compare all overloads including varargs in a single pass.
This commit is contained in:
+8
-11
@@ -88,17 +88,9 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
CandidateCallWithArgumentMapping.create(candidateCall) { it.arguments.filter { it.getArgumentExpression() != null } }
|
CandidateCallWithArgumentMapping.create(candidateCall) { it.arguments.filter { it.getArgumentExpression() != null } }
|
||||||
}
|
}
|
||||||
|
|
||||||
val (varargCandidates, regularCandidates) = conflictingCandidates.partition { it.resultingDescriptor.hasVarargs }
|
val mostSpecificCandidates = conflictingCandidates.selectMostSpecificCallsWithArgumentMapping(discriminateGenericDescriptors)
|
||||||
val mostSpecificRegularCandidates = regularCandidates.selectMostSpecificCallsWithArgumentMapping(discriminateGenericDescriptors)
|
|
||||||
|
|
||||||
return when {
|
return mostSpecificCandidates.singleOrNull()
|
||||||
mostSpecificRegularCandidates.size > 1 ->
|
|
||||||
null
|
|
||||||
mostSpecificRegularCandidates.size == 1 ->
|
|
||||||
mostSpecificRegularCandidates.single()
|
|
||||||
else ->
|
|
||||||
varargCandidates.selectMostSpecificCallsWithArgumentMapping(discriminateGenericDescriptors).singleOrNull()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableDescriptor, K> Collection<CandidateCallWithArgumentMapping<D, K>>.selectMostSpecificCallsWithArgumentMapping(
|
private fun <D : CallableDescriptor, K> Collection<CandidateCallWithArgumentMapping<D, K>>.selectMostSpecificCallsWithArgumentMapping(
|
||||||
@@ -139,7 +131,7 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns `true` if `d1` is definitely not less specific than `d2`,
|
* Returns `true` if `d1` is definitely not less specific than `d2`,
|
||||||
* `false` if `d1` is definitely less specific than `d2` or undecided.
|
* `false` otherwise.
|
||||||
*/
|
*/
|
||||||
private fun <D : CallableDescriptor, K> compareCallsWithArgumentMapping(
|
private fun <D : CallableDescriptor, K> compareCallsWithArgumentMapping(
|
||||||
call1: CandidateCallWithArgumentMapping<D, K>,
|
call1: CandidateCallWithArgumentMapping<D, K>,
|
||||||
@@ -160,6 +152,11 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val hasVarargs1 = call1.resultingDescriptor.hasVarargs
|
||||||
|
val hasVarargs2 = call2.resultingDescriptor.hasVarargs
|
||||||
|
if (hasVarargs1 && !hasVarargs2) return false
|
||||||
|
if (!hasVarargs1 && hasVarargs2) return true
|
||||||
|
|
||||||
assert(call1.argumentsCount == call2.argumentsCount) {
|
assert(call1.argumentsCount == call2.argumentsCount) {
|
||||||
"$call1 and $call2 have different number of explicit arguments"
|
"$call1 and $call2 have different number of explicit arguments"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
object Right
|
||||||
|
object Wrong
|
||||||
|
|
||||||
|
interface A<T>
|
||||||
|
interface B<T> : A<T>
|
||||||
|
|
||||||
|
fun <T> foo(vararg t: T) = Wrong
|
||||||
|
fun <T> foo(t: A<T>) = Wrong
|
||||||
|
fun <T> foo(t: B<T>) = Right
|
||||||
|
|
||||||
|
fun test(b: B<Int>): Right = foo(b)
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T> foo(/*0*/ t: A<T>): Wrong
|
||||||
|
public fun </*0*/ T> foo(/*0*/ t: B<T>): Right
|
||||||
|
public fun </*0*/ T> foo(/*0*/ vararg t: T /*kotlin.Array<out T>*/): Wrong
|
||||||
|
public fun test(/*0*/ b: B<kotlin.Int>): Right
|
||||||
|
|
||||||
|
public interface A</*0*/ T> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface B</*0*/ T> : A<T> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Right {
|
||||||
|
private constructor Right()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Wrong {
|
||||||
|
private constructor Wrong()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -13742,6 +13742,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt10472.kt")
|
||||||
|
public void testKt10472() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/kt10472.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("numberOfDefaults.kt")
|
@TestMetadata("numberOfDefaults.kt")
|
||||||
public void testNumberOfDefaults() throws Exception {
|
public void testNumberOfDefaults() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user