[FIR] Extract ResolutionStageRunner component
That component is responsible to run all resolution stages on candidate and calculating resulting applicability. This is needed for completion of `when` and `try` as function calls
This commit is contained in:
committed by
Mikhail Glukhikh
parent
8bbb60df25
commit
53404e5dac
@@ -41,7 +41,8 @@ class FirCallResolver(
|
||||
private val scopes: List<FirScope>,
|
||||
private val localScopes: List<FirScope>,
|
||||
private val implicitReceiverStack: List<ImplicitReceiverValue>,
|
||||
private val qualifiedResolver: FirQualifiedNameResolver
|
||||
private val qualifiedResolver: FirQualifiedNameResolver,
|
||||
private val resolutionStageRunner: ResolutionStageRunner
|
||||
) : BodyResolveComponents by transformer {
|
||||
|
||||
fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, expectedTypeRef: FirTypeRef?, file: FirFile): FirFunctionCall {
|
||||
@@ -66,7 +67,7 @@ class FirCallResolver(
|
||||
file,
|
||||
transformer.container
|
||||
) { it.resultType }
|
||||
val resolver = CallResolver(returnTypeCalculator, inferenceComponents)
|
||||
val resolver = CallResolver(returnTypeCalculator, inferenceComponents, resolutionStageRunner)
|
||||
resolver.callInfo = info
|
||||
resolver.scopes = (scopes + localScopes).asReversed()
|
||||
|
||||
@@ -156,7 +157,7 @@ class FirCallResolver(
|
||||
file,
|
||||
transformer.container
|
||||
) { it.resultType }
|
||||
val resolver = CallResolver(returnTypeCalculator, inferenceComponents)
|
||||
val resolver = CallResolver(returnTypeCalculator, inferenceComponents, resolutionStageRunner)
|
||||
resolver.callInfo = info
|
||||
resolver.scopes = (scopes + localScopes).asReversed()
|
||||
|
||||
|
||||
@@ -14,7 +14,11 @@ enum class TowerDataKind {
|
||||
TOWER_LEVEL
|
||||
}
|
||||
|
||||
class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: InferenceComponents) {
|
||||
class CallResolver(
|
||||
val typeCalculator: ReturnTypeCalculator,
|
||||
val components: InferenceComponents,
|
||||
val resolutionStageRunner: ResolutionStageRunner
|
||||
) {
|
||||
var callInfo: CallInfo? = null
|
||||
var scopes: List<FirScope>? = null
|
||||
|
||||
@@ -51,7 +55,7 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
|
||||
return group
|
||||
}
|
||||
|
||||
val collector by lazy { CandidateCollector(components) }
|
||||
val collector by lazy { CandidateCollector(components, resolutionStageRunner) }
|
||||
lateinit var towerDataConsumer: TowerDataConsumer
|
||||
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue>
|
||||
|
||||
|
||||
+8
-39
@@ -9,14 +9,11 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImp
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
open class CandidateCollector(val components: InferenceComponents) {
|
||||
|
||||
open class CandidateCollector(
|
||||
val components: InferenceComponents,
|
||||
val resolutionStageRunner: ResolutionStageRunner
|
||||
) {
|
||||
val groupNumbers = mutableListOf<Int>()
|
||||
val candidates = mutableListOf<Candidate>()
|
||||
|
||||
@@ -28,37 +25,8 @@ open class CandidateCollector(val components: InferenceComponents) {
|
||||
currentApplicability = CandidateApplicability.HIDDEN
|
||||
}
|
||||
|
||||
private fun getApplicability(
|
||||
group: Int,
|
||||
candidate: Candidate
|
||||
): CandidateApplicability {
|
||||
val sink = CheckerSinkImpl(components)
|
||||
var finished = false
|
||||
sink.continuation = suspend {
|
||||
for (stage in candidate.callInfo.callKind.sequence()) {
|
||||
stage.check(candidate, sink, candidate.callInfo)
|
||||
}
|
||||
}.createCoroutineUnintercepted(completion = object : Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resumeWith(result: Result<Unit>) {
|
||||
result.exceptionOrNull()?.let { throw it }
|
||||
finished = true
|
||||
}
|
||||
})
|
||||
|
||||
while (!finished) {
|
||||
sink.continuation!!.resume(Unit)
|
||||
if (sink.current < CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return sink.current
|
||||
}
|
||||
|
||||
open fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
||||
val applicability = getApplicability(group, candidate)
|
||||
val applicability = resolutionStageRunner.processCandidate(candidate)
|
||||
|
||||
if (applicability > currentApplicability) {
|
||||
groupNumbers.clear()
|
||||
@@ -103,8 +71,9 @@ class InvokeReceiverCandidateCollector(
|
||||
val callResolver: CallResolver,
|
||||
val invokeCallInfo: CallInfo,
|
||||
components: InferenceComponents,
|
||||
val invokeConsumer: AccumulatingTowerDataConsumer
|
||||
) : CandidateCollector(components) {
|
||||
val invokeConsumer: AccumulatingTowerDataConsumer,
|
||||
resolutionStageRunner: ResolutionStageRunner
|
||||
) : CandidateCollector(components, resolutionStageRunner) {
|
||||
override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
||||
val applicability = super.consumeCandidate(group, candidate)
|
||||
|
||||
|
||||
+2
-1
@@ -94,7 +94,8 @@ fun createFunctionConsumer(
|
||||
callResolver,
|
||||
invokeCallInfo = callInfo,
|
||||
components = inferenceComponents,
|
||||
invokeConsumer = this
|
||||
invokeConsumer = this,
|
||||
resolutionStageRunner = resultCollector.resolutionStageRunner
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir.resolve.calls
|
||||
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
class ResolutionStageRunner(val components: InferenceComponents) {
|
||||
fun processCandidate(candidate: Candidate): CandidateApplicability {
|
||||
val sink = CheckerSinkImpl(components)
|
||||
var finished = false
|
||||
sink.continuation = suspend {
|
||||
for (stage in candidate.callInfo.callKind.sequence()) {
|
||||
stage.check(candidate, sink, candidate.callInfo)
|
||||
}
|
||||
}.createCoroutineUnintercepted(completion = object : Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resumeWith(result: Result<Unit>) {
|
||||
result.exceptionOrNull()?.let { throw it }
|
||||
finished = true
|
||||
}
|
||||
})
|
||||
|
||||
while (!finished) {
|
||||
sink.continuation!!.resume(Unit)
|
||||
if (sink.current < CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return sink.current
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -71,7 +71,16 @@ open class FirBodyResolveTransformer(
|
||||
|
||||
private val callCompleter: FirCallCompleter = FirCallCompleter(this, inferenceComponents)
|
||||
private val qualifiedResolver: FirQualifiedNameResolver = FirQualifiedNameResolver(this)
|
||||
private val callResolver: FirCallResolver = FirCallResolver(this, inferenceComponents, scopes, localScopes, implicitReceiverStack, qualifiedResolver)
|
||||
private val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner(inferenceComponents)
|
||||
private val callResolver: FirCallResolver = FirCallResolver(
|
||||
this,
|
||||
inferenceComponents,
|
||||
scopes,
|
||||
localScopes,
|
||||
implicitReceiverStack,
|
||||
qualifiedResolver,
|
||||
resolutionStageRunner
|
||||
)
|
||||
|
||||
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
|
||||
packageFqName = file.packageFqName
|
||||
|
||||
Reference in New Issue
Block a user