[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) {
|
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||||
bestCandidates.toSet()
|
bestCandidates.toSet()
|
||||||
} else {
|
} else {
|
||||||
conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = false)
|
conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+11
-6
@@ -33,19 +33,19 @@ class ConeOverloadConflictResolver(
|
|||||||
fun chooseMaximallySpecificCandidates(
|
fun chooseMaximallySpecificCandidates(
|
||||||
candidates: Collection<Candidate>,
|
candidates: Collection<Candidate>,
|
||||||
//checkArgumentsMode: CheckArgumentTypesMode,
|
//checkArgumentsMode: CheckArgumentTypesMode,
|
||||||
discriminateGenerics: Boolean//,
|
discriminateGenerics: Boolean
|
||||||
//isDebuggerContext: Boolean
|
|
||||||
): Set<Candidate> {
|
): Set<Candidate> {
|
||||||
|
candidates.setIfOneOrEmpty()?.let { return it }
|
||||||
|
|
||||||
val candidatesSet = candidates.toSet()
|
val candidatesSet = candidates.toSet()
|
||||||
|
|
||||||
val maximallySpecific = findMaximallySpecificCall(candidatesSet, false/*, isDebuggerContext*/)
|
findMaximallySpecificCall(candidatesSet, false)?.let { return setOf(it) }
|
||||||
if (maximallySpecific != null) {
|
|
||||||
return setOf(maximallySpecific)
|
if (discriminateGenerics) {
|
||||||
|
findMaximallySpecificCall(candidatesSet, true)?.let { return setOf(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return candidatesSet
|
return candidatesSet
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createFlatSignature(call: Candidate): FlatSignature<Candidate> {
|
private fun createFlatSignature(call: Candidate): FlatSignature<Candidate> {
|
||||||
@@ -224,6 +224,11 @@ class ConeOverloadConflictResolver(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <C> Collection<C>.setIfOneOrEmpty(): Set<C>? = when (size) {
|
||||||
|
0 -> emptySet()
|
||||||
|
1 -> setOf(single())
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object NoSubstitutor : TypeSubstitutorMarker
|
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|)
|
||||||
|
}
|
||||||
@@ -22,13 +22,3 @@ class Derived : Base<Int>(10)
|
|||||||
val xx = Derived().x + 1
|
val xx = Derived().x + 1
|
||||||
|
|
||||||
val t = throw AssertionError("")
|
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<!>()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -57,22 +57,3 @@ FILE: problems.kt
|
|||||||
public get(): R|kotlin/Int|
|
public get(): R|kotlin/Int|
|
||||||
public final val t: R|kotlin/Nothing| = throw R|java/lang/AssertionError.AssertionError|(String())
|
public final val t: R|kotlin/Nothing| = throw R|java/lang/AssertionError.AssertionError|(String())
|
||||||
public get(): R|kotlin/Nothing|
|
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");
|
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")
|
@TestMetadata("overloadWithDefault.kt")
|
||||||
public void testOverloadWithDefault() throws Exception {
|
public void testOverloadWithDefault() throws Exception {
|
||||||
runTest("compiler/fir/resolve/testData/resolve/arguments/overloadWithDefault.kt");
|
runTest("compiler/fir/resolve/testData/resolve/arguments/overloadWithDefault.kt");
|
||||||
|
|||||||
+2
-13
@@ -2,17 +2,6 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
// !USE_EXPERIMENTAL: kotlin.Experimental
|
// !USE_EXPERIMENTAL: kotlin.Experimental
|
||||||
|
|
||||||
import kotlin.experimental.ExperimentalTypeInference
|
fun test(x: List<Int>) {
|
||||||
|
x + x
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user