[FIR] Add discriminating generics into ConeOverloadConflictResolver
This commit is contained in:
@@ -93,7 +93,7 @@ class FirCallResolver(
|
||||
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||
bestCandidates.toSet()
|
||||
} else {
|
||||
conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = false)
|
||||
conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+11
-6
@@ -33,19 +33,19 @@ class ConeOverloadConflictResolver(
|
||||
fun chooseMaximallySpecificCandidates(
|
||||
candidates: Collection<Candidate>,
|
||||
//checkArgumentsMode: CheckArgumentTypesMode,
|
||||
discriminateGenerics: Boolean//,
|
||||
//isDebuggerContext: Boolean
|
||||
discriminateGenerics: Boolean
|
||||
): Set<Candidate> {
|
||||
candidates.setIfOneOrEmpty()?.let { return it }
|
||||
|
||||
val candidatesSet = candidates.toSet()
|
||||
|
||||
val maximallySpecific = findMaximallySpecificCall(candidatesSet, false/*, isDebuggerContext*/)
|
||||
if (maximallySpecific != null) {
|
||||
return setOf(maximallySpecific)
|
||||
findMaximallySpecificCall(candidatesSet, false)?.let { return setOf(it) }
|
||||
|
||||
if (discriminateGenerics) {
|
||||
findMaximallySpecificCall(candidatesSet, true)?.let { return setOf(it) }
|
||||
}
|
||||
|
||||
return candidatesSet
|
||||
|
||||
}
|
||||
|
||||
private fun createFlatSignature(call: Candidate): FlatSignature<Candidate> {
|
||||
@@ -224,6 +224,11 @@ class ConeOverloadConflictResolver(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun <C> Collection<C>.setIfOneOrEmpty(): Set<C>? = when (size) {
|
||||
0 -> emptySet()
|
||||
1 -> setOf(single())
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
object NoSubstitutor : TypeSubstitutorMarker
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
interface A
|
||||
|
||||
interface B : A
|
||||
|
||||
interface C
|
||||
|
||||
interface D : B, C
|
||||
|
||||
fun B.foo(): Int = 1
|
||||
fun <T> T.foo(): String where T : A, T : C = ""
|
||||
|
||||
fun takeInt(x: Int) {}
|
||||
|
||||
fun test(d: D) {
|
||||
val x = d.foo()
|
||||
takeInt(x)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
FILE: overloadByReceiver.kt
|
||||
public abstract interface A : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface B : R|A| {
|
||||
}
|
||||
public abstract interface C : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface D : R|B|, R|C| {
|
||||
}
|
||||
public final fun R|B|.foo(): R|kotlin/Int| {
|
||||
^foo Int(1)
|
||||
}
|
||||
public final fun <T : R|A|, R|C|> R|T|.foo(): R|kotlin/String| {
|
||||
^foo String()
|
||||
}
|
||||
public final fun takeInt(x: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun test(d: R|D|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Int| = R|<local>/d|.R|/foo|()
|
||||
R|/takeInt|(R|<local>/x|)
|
||||
}
|
||||
+1
-11
@@ -21,14 +21,4 @@ class Base<T>(val x: T)
|
||||
class Derived : Base<Int>(10)
|
||||
val xx = Derived().x + 1
|
||||
|
||||
val t = throw AssertionError("")
|
||||
|
||||
interface A
|
||||
interface B
|
||||
interface C : A
|
||||
class BC : B, C
|
||||
fun C.analyze() {}
|
||||
inline fun <reified T> T.analyze() where T : A, T : B {}
|
||||
fun testAnalyze() {
|
||||
BC().<!AMBIGUITY!>analyze<!>()
|
||||
}
|
||||
val t = throw AssertionError("")
|
||||
@@ -57,22 +57,3 @@ FILE: problems.kt
|
||||
public get(): R|kotlin/Int|
|
||||
public final val t: R|kotlin/Nothing| = throw R|java/lang/AssertionError.AssertionError|(String())
|
||||
public get(): R|kotlin/Nothing|
|
||||
public abstract interface A : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface B : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface C : R|A| {
|
||||
}
|
||||
public final class BC : R|B|, R|C| {
|
||||
public constructor(): R|BC| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final fun R|C|.analyze(): R|kotlin/Unit| {
|
||||
}
|
||||
public final inline fun <reified T : R|A|, R|B|> R|T|.analyze(): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun testAnalyze(): R|kotlin/Unit| {
|
||||
R|/BC.BC|().<Ambiguity: analyze, [/analyze, /analyze]>#()
|
||||
}
|
||||
|
||||
+5
@@ -235,6 +235,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/arguments/lambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overloadByReceiver.kt")
|
||||
public void testOverloadByReceiver() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/arguments/overloadByReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overloadWithDefault.kt")
|
||||
public void testOverloadWithDefault() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/arguments/overloadWithDefault.kt");
|
||||
|
||||
+3
-14
@@ -2,17 +2,6 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !USE_EXPERIMENTAL: kotlin.Experimental
|
||||
|
||||
import kotlin.experimental.ExperimentalTypeInference
|
||||
|
||||
interface ProducerScope<E> {
|
||||
fun yield(e: E)
|
||||
}
|
||||
|
||||
@UseExperimental(ExperimentalTypeInference::class)
|
||||
fun <E> produce(@BuilderInference block: ProducerScope<E>.() -> Unit): ProducerScope<E> = TODO()
|
||||
|
||||
fun <K> filter(e: K, predicate: (K) -> Boolean) =
|
||||
produce {
|
||||
predicate(e)
|
||||
yield(42)
|
||||
}
|
||||
fun test(x: List<Int>) {
|
||||
x + x
|
||||
}
|
||||
Reference in New Issue
Block a user