[FIR] Move tracking candidate applicability from CheckerSink to Candidate

This commit is contained in:
Dmitriy Novozhilov
2020-11-10 17:54:52 +03:00
parent f1ac1f177b
commit 67b262aa34
10 changed files with 31 additions and 36 deletions
@@ -158,7 +158,7 @@ class FirOverloadByLambdaReturnTypeResolver(
val successfulCandidates = mutableSetOf<Candidate>() val successfulCandidates = mutableSetOf<Candidate>()
for (candidate in candidates) { for (candidate in candidates) {
if (candidate.isSuccessful()) { if (candidate.isSuccessful) {
successfulCandidates += candidate successfulCandidates += candidate
} else { } else {
errorCandidates += candidate errorCandidates += candidate
@@ -109,17 +109,22 @@ class Candidate(
lateinit var typeArgumentMapping: TypeArgumentMapping lateinit var typeArgumentMapping: TypeArgumentMapping
val postponedAtoms = mutableListOf<PostponedResolvedAtom>() val postponedAtoms = mutableListOf<PostponedResolvedAtom>()
val diagnostics: MutableList<ResolutionDiagnostic> = mutableListOf() var currentApplicability = CandidateApplicability.RESOLVED
private set
private val _diagnostics: MutableList<ResolutionDiagnostic> = mutableListOf()
val diagnostics: List<ResolutionDiagnostic>
get() = _diagnostics
fun addDiagnostic(diagnostic: ResolutionDiagnostic) { fun addDiagnostic(diagnostic: ResolutionDiagnostic) {
diagnostics += diagnostic _diagnostics += diagnostic
if (diagnostic.applicability < currentApplicability) {
currentApplicability = diagnostic.applicability
}
} }
fun isSuccessful(): Boolean { val isSuccessful: Boolean
if (system.hasContradiction) return false get() = currentApplicability.isSuccess && (!systemInitialized || !system.hasContradiction)
val currentApplicability = diagnostics.map { it.applicability }.minOrNull() ?: CandidateApplicability.RESOLVED
return currentApplicability.isSuccess
}
var passedStages: Int = 0 var passedStages: Int = 0
@@ -32,20 +32,12 @@ suspend inline fun CheckerSink.yieldDiagnostic(diagnostic: ResolutionDiagnostic)
} }
class CheckerSinkImpl( class CheckerSinkImpl(
private val candidate: Candidate,
var continuation: Continuation<Unit>? = null, var continuation: Continuation<Unit>? = null,
val stopOnFirstError: Boolean = true val stopOnFirstError: Boolean = true,
) : CheckerSink() { ) : CheckerSink() {
var currentApplicability = CandidateApplicability.RESOLVED
private set
private val _diagnostics: MutableList<ResolutionDiagnostic> = mutableListOf()
val diagnostics: List<ResolutionDiagnostic>
get() = _diagnostics
override fun reportDiagnostic(diagnostic: ResolutionDiagnostic) { override fun reportDiagnostic(diagnostic: ResolutionDiagnostic) {
_diagnostics += diagnostic candidate.addDiagnostic(diagnostic)
if (diagnostic.applicability < currentApplicability) currentApplicability = diagnostic.applicability
} }
@PrivateForInline @PrivateForInline
@@ -55,6 +47,5 @@ class CheckerSinkImpl(
} }
override val needYielding: Boolean override val needYielding: Boolean
get() = stopOnFirstError && !currentApplicability.isSuccess get() = stopOnFirstError && !candidate.isSuccessful
} }
@@ -15,7 +15,7 @@ import kotlin.coroutines.resume
class ResolutionStageRunner { class ResolutionStageRunner {
fun processCandidate(candidate: Candidate, context: ResolutionContext, stopOnFirstError: Boolean = true): CandidateApplicability { fun processCandidate(candidate: Candidate, context: ResolutionContext, stopOnFirstError: Boolean = true): CandidateApplicability {
val sink = CheckerSinkImpl(stopOnFirstError = stopOnFirstError) val sink = CheckerSinkImpl(candidate, stopOnFirstError = stopOnFirstError)
var finished = false var finished = false
sink.continuation = suspend { sink.continuation = suspend {
candidate.callInfo.callKind.resolutionSequence.forEachIndexed { index, stage -> candidate.callInfo.callKind.resolutionSequence.forEachIndexed { index, stage ->
@@ -35,11 +35,10 @@ class ResolutionStageRunner {
while (!finished) { while (!finished) {
sink.continuation!!.resume(Unit) sink.continuation!!.resume(Unit)
if (!sink.currentApplicability.isSuccess) { if (!candidate.isSuccessful) {
break break
} }
} }
candidate.diagnostics += sink.diagnostics return candidate.currentApplicability
return sink.currentApplicability
} }
} }
@@ -162,7 +162,7 @@ class PostponedArgumentsAnalyzer(
returnArguments.forEach { c.addSubsystemFromExpression(it) } returnArguments.forEach { c.addSubsystemFromExpression(it) }
val checkerSink: CheckerSink = CheckerSinkImpl() val checkerSink: CheckerSink = CheckerSinkImpl(candidate)
var hasExpressionInReturnArguments = false var hasExpressionInReturnArguments = false
val lambdaReturnType = lambda.returnType.let(substitute).takeUnless { it.isUnit } val lambdaReturnType = lambda.returnType.let(substitute).takeUnless { it.isUnit }
@@ -11,7 +11,7 @@ fun test() {
const val <T> a3 = 0 const val <T> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!> <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!>
val <T> a5 by Delegate<Int>() val <T> a5 by Delegate<Int>()
val <T> a6 by <!INAPPLICABLE_CANDIDATE!>Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()<!> val <T> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()
} }
class Delegate<F> { class Delegate<F> {
@@ -11,7 +11,7 @@ fun test() {
const val <T> a3 = 0 const val <T> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!> <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!>
val <T> a5 by Delegate<Int>() val <T> a5 by Delegate<Int>()
val <T> a6 by <!INAPPLICABLE_CANDIDATE!>Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()<!> val <T> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()
} }
class Delegate<F> { class Delegate<F> {
@@ -5,7 +5,7 @@
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
class B { class B {
val c by <!INAPPLICABLE_CANDIDATE!><!INAPPLICABLE_CANDIDATE!>Delegate<!>(<!UNRESOLVED_REFERENCE!>ag<!>)<!> val c by <!INAPPLICABLE_CANDIDATE!>Delegate<!>(<!UNRESOLVED_REFERENCE!>ag<!>)
} }
class Delegate<T: Any>(val init: T) { class Delegate<T: Any>(val init: T) {
@@ -5,5 +5,5 @@ fun interface Bar {
operator fun Bar.plus(b: Bar): String = invoke() + b.invoke() operator fun Bar.plus(b: Bar): String = invoke() + b.invoke()
fun box(): String { fun box(): String {
return { "O" } <!INAPPLICABLE_CANDIDATE!>+<!> { "K" } return { "O" } + { "K" }
} }
@@ -14,14 +14,14 @@ class A<T> {
fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) { fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
a.<!INAPPLICABLE_CANDIDATE!>foo1<!>(Out<CharSequence>()) a.<!INAPPLICABLE_CANDIDATE!>foo1<!>(Out<CharSequence>())
a.<!INAPPLICABLE_CANDIDATE!>foo1<!><Out<CharSequence>>(Out()) a.foo1<<!UPPER_BOUND_VIOLATED!>Out<CharSequence><!>>(Out())
a.foo1(Out()) a.foo1(Out())
a.foo1(Out<Nothing>()) a.foo1(Out<Nothing>())
a.foo2(Inv()) a.foo2(Inv())
a.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>()) a.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>())
a.<!INAPPLICABLE_CANDIDATE!>foo2<!><Inv<CharSequence>>(Inv()) a.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(Inv())
a.foo3(In()) a.foo3(In())
a.foo3(In<CharSequence>()) a.foo3(In<CharSequence>())
@@ -33,11 +33,11 @@ fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
b.foo2(Inv()) b.foo2(Inv())
b.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>()) b.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>())
b.<!INAPPLICABLE_CANDIDATE!>foo2<!><Inv<CharSequence>>(Inv()) b.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(Inv())
b.<!INAPPLICABLE_CANDIDATE!>foo3<!>(In<CharSequence>()) b.<!INAPPLICABLE_CANDIDATE!>foo3<!>(In<CharSequence>())
b.<!INAPPLICABLE_CANDIDATE!>foo3<!><In<CharSequence>>(In()) b.foo3<<!UPPER_BOUND_VIOLATED!>In<CharSequence><!>>(In())
b.foo3(In<Any?>()) b.foo3(In<Any?>())
b.foo3(In()) b.foo3(In())