Cone conflict resolver: filter equivalent top-level callables
This commit is contained in:
+46
-1
@@ -37,7 +37,7 @@ class ConeOverloadConflictResolver(
|
||||
): Set<Candidate> {
|
||||
candidates.setIfOneOrEmpty()?.let { return it }
|
||||
|
||||
val candidatesSet = candidates.toSet()
|
||||
val candidatesSet = filterOutEquivalentCalls(candidates)
|
||||
|
||||
findMaximallySpecificCall(candidatesSet, false)?.let { return setOf(it) }
|
||||
|
||||
@@ -48,6 +48,42 @@ class ConeOverloadConflictResolver(
|
||||
return candidatesSet
|
||||
}
|
||||
|
||||
private fun filterOutEquivalentCalls(candidates: Collection<Candidate>): Set<Candidate> {
|
||||
val result = mutableSetOf<Candidate>()
|
||||
outerLoop@ for (myCandidate in candidates) {
|
||||
val me = myCandidate.symbol.fir
|
||||
if (me is FirCallableMemberDeclaration<*> && me.symbol.callableId.className == null) {
|
||||
for (otherCandidate in result) {
|
||||
val other = otherCandidate.symbol.fir
|
||||
if (other is FirCallableMemberDeclaration<*> && other.symbol.callableId.className == null) {
|
||||
if (areEquivalentTopLevelCallables(me, myCandidate, other, otherCandidate)) {
|
||||
continue@outerLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result += myCandidate
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun areEquivalentTopLevelCallables(
|
||||
first: FirCallableMemberDeclaration<*>,
|
||||
firstCandidate: Candidate,
|
||||
second: FirCallableMemberDeclaration<*>,
|
||||
secondCandidate: Candidate
|
||||
): Boolean {
|
||||
if (first.symbol.callableId != second.symbol.callableId) return false
|
||||
if (first.isExpect != second.isExpect) return false
|
||||
if (first.receiverTypeRef?.coneTypeUnsafe<ConeKotlinType>() != second.receiverTypeRef?.coneTypeUnsafe()) {
|
||||
return false
|
||||
}
|
||||
val firstSignature = createFlatSignature(firstCandidate, first)
|
||||
val secondSignature = createFlatSignature(secondCandidate, second)
|
||||
return compareCallsByUsedArguments(firstSignature, secondSignature, false) &&
|
||||
compareCallsByUsedArguments(secondSignature, firstSignature, false)
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate): FlatSignature<Candidate> {
|
||||
return when (val declaration = call.symbol.fir) {
|
||||
is FirSimpleFunction -> createFlatSignature(call, declaration)
|
||||
@@ -58,6 +94,15 @@ class ConeOverloadConflictResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, declaration: FirCallableMemberDeclaration<*>): FlatSignature<Candidate> {
|
||||
return when (declaration) {
|
||||
is FirSimpleFunction -> createFlatSignature(call, declaration)
|
||||
is FirConstructor -> createFlatSignature(call, declaration)
|
||||
is FirVariable<*> -> createFlatSignature(call, declaration as FirVariable<*>)
|
||||
else -> error("Not supported: $declaration")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate, constructor: FirConstructor): FlatSignature<Candidate> {
|
||||
return FlatSignature(
|
||||
call,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
val x: Array<String> = emptyArray()
|
||||
|
||||
val y: Array<String>
|
||||
get() = emptyArray()
|
||||
|
||||
interface My
|
||||
|
||||
val z: Array<out My>
|
||||
get() = emptyArray()
|
||||
@@ -0,0 +1,13 @@
|
||||
FILE: emptyArray.kt
|
||||
public final val x: R|kotlin/Array<kotlin/String>| = R|kotlin/emptyArray|<R|kotlin/String|>()
|
||||
public get(): R|kotlin/Array<kotlin/String>|
|
||||
public final val y: R|kotlin/Array<kotlin/String>|
|
||||
public get(): R|kotlin/Array<kotlin/String>| {
|
||||
^ R|kotlin/emptyArray|<R|kotlin/String|>()
|
||||
}
|
||||
public abstract interface My : R|kotlin/Any| {
|
||||
}
|
||||
public final val z: R|kotlin/Array<out My>|
|
||||
public get(): R|kotlin/Array<out My>| {
|
||||
^ R|kotlin/emptyArray|<R|My|>()
|
||||
}
|
||||
Generated
+5
@@ -68,6 +68,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
|
||||
runTest("compiler/fir/resolve/testData/resolve/stdlib/concurrent.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyArray.kt")
|
||||
public void testEmptyArray() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/stdlib/emptyArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exception.kt")
|
||||
public void testException() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/stdlib/exception.kt");
|
||||
|
||||
Reference in New Issue
Block a user