diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolutionCandidate.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolutionCandidate.kt new file mode 100644 index 00000000000..535af22cce8 --- /dev/null +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolutionCandidate.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.calls.model + +import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks +import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem +import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage +import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl +import org.jetbrains.kotlin.resolve.calls.tower.Candidate +import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability +import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower +import org.jetbrains.kotlin.types.TypeSubstitutor + +/** + * baseSystem contains all information from arguments, i.e. it is union of all system of arguments + * Also by convention we suppose that baseSystem has no contradiction + */ +class KotlinResolutionCandidate( + val callComponents: KotlinCallComponents, + val resolutionCallbacks: KotlinResolutionCallbacks, + val callableReferenceResolver: CallableReferenceResolver, + val scopeTower: ImplicitScopeTower, + private val baseSystem: ConstraintStorage, + val resolvedCall: MutableResolvedCallAtom, + val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null, + private val resolutionSequence: List = resolvedCall.atom.callKind.resolutionSequence +) : Candidate, KotlinDiagnosticsHolder { + val diagnosticsFromResolutionParts = arrayListOf() // TODO: this is mutable list, take diagnostics only once! + private var newSystem: NewConstraintSystemImpl? = null + private var currentApplicability = CandidateApplicability.RESOLVED + private var subResolvedAtoms: MutableList = arrayListOf() + + private val stepCount = resolutionSequence.sumOf { it.run { workCount() } } + private var step = 0 + + fun getSystem(): NewConstraintSystem { + if (newSystem == null) { + newSystem = + NewConstraintSystemImpl(callComponents.constraintInjector, callComponents.builtIns, callComponents.kotlinTypeRefiner) + newSystem!!.addOtherSystem(baseSystem) + } + return newSystem!! + } + + internal val csBuilder get() = getSystem().getBuilder() + + override fun addDiagnostic(diagnostic: KotlinCallDiagnostic) { + diagnosticsFromResolutionParts.add(diagnostic) + currentApplicability = minOf(diagnostic.candidateApplicability, currentApplicability) + } + + fun getSubResolvedAtoms(): List = subResolvedAtoms + + fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom) { + subResolvedAtoms.add(resolvedAtom) + } + + private fun processParts(stopOnFirstError: Boolean) { + if (stopOnFirstError && step > 0) return // error already happened + if (step == stepCount) return + + var partIndex = 0 + var workStep = step + while (workStep > 0) { + val workCount = resolutionSequence[partIndex].run { workCount() } + if (workStep >= workCount) { + partIndex++ + workStep -= workCount + } else { + break + } + } + if (partIndex < resolutionSequence.size) { + if (processPart(resolutionSequence[partIndex], stopOnFirstError, workStep)) return + partIndex++ + } + + while (partIndex < resolutionSequence.size) { + if (processPart(resolutionSequence[partIndex], stopOnFirstError)) return + partIndex++ + } + if (step == stepCount) { + resolvedCall.setAnalyzedResults(subResolvedAtoms) + } + } + + // true if part was interrupted + private fun processPart(part: ResolutionPart, stopOnFirstError: Boolean, startWorkIndex: Int = 0): Boolean { + for (workIndex in startWorkIndex until (part.run { workCount() })) { + if (stopOnFirstError && !currentApplicability.isSuccess) return true + + part.run { process(workIndex) } + step++ + } + return false + } + + val variableCandidateIfInvoke: KotlinResolutionCandidate? + get() = callComponents.statelessCallbacks.getVariableCandidateIfInvoke(resolvedCall.atom) + + private val variableApplicability + get() = variableCandidateIfInvoke?.resultingApplicability ?: CandidateApplicability.RESOLVED + + override val isSuccessful: Boolean + get() { + processParts(stopOnFirstError = true) + return currentApplicability.isSuccess && variableApplicability.isSuccess && !getSystem().hasContradiction + } + + override val resultingApplicability: CandidateApplicability + get() { + processParts(stopOnFirstError = false) + + val systemApplicability = getResultApplicability(getSystem().errors) + return minOf(currentApplicability, systemApplicability, variableApplicability) + } + + override fun addCompatibilityWarning(other: Candidate) { + if (this !== other && other is KotlinResolutionCandidate) { + addDiagnostic(CompatibilityWarning(other.resolvedCall.candidateDescriptor)) + } + } + + override fun toString(): String { + val descriptor = DescriptorRenderer.COMPACT.render(resolvedCall.candidateDescriptor) + val okOrFail = if (currentApplicability.isSuccess) "OK" else "FAIL" + val step = "$step/$stepCount" + return "$okOrFail($step): $descriptor" + } +} \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallAtoms.kt similarity index 58% rename from compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt rename to compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallAtoms.kt index f47c2dc136b..7768771a478 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallAtoms.kt @@ -68,123 +68,6 @@ fun KotlinDiagnosticsHolder.addError(error: ConstraintSystemError) { addDiagnostic(error.asDiagnostic()) } -/** - * baseSystem contains all information from arguments, i.e. it is union of all system of arguments - * Also by convention we suppose that baseSystem has no contradiction - */ -class KotlinResolutionCandidate( - val callComponents: KotlinCallComponents, - val resolutionCallbacks: KotlinResolutionCallbacks, - val callableReferenceResolver: CallableReferenceResolver, - val scopeTower: ImplicitScopeTower, - private val baseSystem: ConstraintStorage, - val resolvedCall: MutableResolvedCallAtom, - val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null, - private val resolutionSequence: List = resolvedCall.atom.callKind.resolutionSequence -) : Candidate, KotlinDiagnosticsHolder { - val diagnosticsFromResolutionParts = arrayListOf() // TODO: this is mutable list, take diagnostics only once! - private var newSystem: NewConstraintSystemImpl? = null - private var currentApplicability = CandidateApplicability.RESOLVED - private var subResolvedAtoms: MutableList = arrayListOf() - - private val stepCount = resolutionSequence.sumOf { it.run { workCount() } } - private var step = 0 - - fun getSystem(): NewConstraintSystem { - if (newSystem == null) { - newSystem = NewConstraintSystemImpl(callComponents.constraintInjector, callComponents.builtIns, callComponents.kotlinTypeRefiner) - newSystem!!.addOtherSystem(baseSystem) - } - return newSystem!! - } - - internal val csBuilder get() = getSystem().getBuilder() - - override fun addDiagnostic(diagnostic: KotlinCallDiagnostic) { - diagnosticsFromResolutionParts.add(diagnostic) - currentApplicability = minOf(diagnostic.candidateApplicability, currentApplicability) - } - - fun getSubResolvedAtoms(): List = subResolvedAtoms - - fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom) { - subResolvedAtoms.add(resolvedAtom) - } - - private fun processParts(stopOnFirstError: Boolean) { - if (stopOnFirstError && step > 0) return // error already happened - if (step == stepCount) return - - var partIndex = 0 - var workStep = step - while (workStep > 0) { - val workCount = resolutionSequence[partIndex].run { workCount() } - if (workStep >= workCount) { - partIndex++ - workStep -= workCount - } else { - break - } - } - if (partIndex < resolutionSequence.size) { - if (processPart(resolutionSequence[partIndex], stopOnFirstError, workStep)) return - partIndex++ - } - - while (partIndex < resolutionSequence.size) { - if (processPart(resolutionSequence[partIndex], stopOnFirstError)) return - partIndex++ - } - if (step == stepCount) { - resolvedCall.setAnalyzedResults(subResolvedAtoms) - } - } - - // true if part was interrupted - private fun processPart(part: ResolutionPart, stopOnFirstError: Boolean, startWorkIndex: Int = 0): Boolean { - for (workIndex in startWorkIndex until (part.run { workCount() })) { - if (stopOnFirstError && !currentApplicability.isSuccess) return true - - part.run { process(workIndex) } - step++ - } - return false - } - - val variableCandidateIfInvoke: KotlinResolutionCandidate? - get() = callComponents.statelessCallbacks.getVariableCandidateIfInvoke(resolvedCall.atom) - - private val variableApplicability - get() = variableCandidateIfInvoke?.resultingApplicability ?: CandidateApplicability.RESOLVED - - override val isSuccessful: Boolean - get() { - processParts(stopOnFirstError = true) - return currentApplicability.isSuccess && variableApplicability.isSuccess && !getSystem().hasContradiction - } - - override val resultingApplicability: CandidateApplicability - get() { - processParts(stopOnFirstError = false) - - val systemApplicability = getResultApplicability(getSystem().errors) - return minOf(currentApplicability, systemApplicability, variableApplicability) - } - - override fun addCompatibilityWarning(other: Candidate) { - if (this !== other && other is KotlinResolutionCandidate) { - addDiagnostic(CompatibilityWarning(other.resolvedCall.candidateDescriptor)) - } - } - - override fun toString(): String { - val descriptor = DescriptorRenderer.COMPACT.render(resolvedCall.candidateDescriptor) - val okOrFail = if (currentApplicability.isSuccess) "OK" else "FAIL" - val step = "$step/$stepCount" - return "$okOrFail($step): $descriptor" - } -} - class MutableResolvedCallAtom( override val atom: KotlinCall, override val candidateDescriptor: CallableDescriptor, // original candidate descriptor