[FIR] Refactor tower resolver to coroutines

This commit is contained in:
simon.ogorodnik
2020-02-11 13:35:29 +03:00
parent 695558465d
commit d775852781
4 changed files with 146 additions and 142 deletions
@@ -79,12 +79,12 @@ class FirTowerResolver(
return implicitReceivers return implicitReceivers
} }
private fun runResolverForQualifierReceiver( private suspend fun runResolverForQualifierReceiver(
info: CallInfo, info: CallInfo,
collector: CandidateCollector, collector: CandidateCollector,
resolvedQualifier: FirResolvedQualifier, resolvedQualifier: FirResolvedQualifier,
manager: TowerResolveManager manager: TowerResolveManager
): CandidateCollector { ) {
val qualifierScopes = if (resolvedQualifier.classId == null) { val qualifierScopes = if (resolvedQualifier.classId == null) {
listOf( listOf(
FirExplicitSimpleImportingScope( FirExplicitSimpleImportingScope(
@@ -107,7 +107,6 @@ class FirTowerResolver(
manager.processLevel( manager.processLevel(
ScopeTowerLevel(session, components, qualifierScope), info.noStubReceiver(), TowerGroup.Qualifier(depth) ScopeTowerLevel(session, components, qualifierScope), info.noStubReceiver(), TowerGroup.Qualifier(depth)
) )
if (collector.isSuccess()) return collector
} }
if (resolvedQualifier.classId != null) { if (resolvedQualifier.classId != null) {
@@ -124,15 +123,13 @@ class FirTowerResolver(
} }
} }
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
return collector
} }
private fun runResolverForNoReceiver( private suspend fun runResolverForNoReceiver(
info: CallInfo, info: CallInfo,
collector: CandidateCollector, collector: CandidateCollector,
manager: TowerResolveManager manager: TowerResolveManager
): CandidateCollector { ) {
val shouldProcessExtensionsBeforeMembers = val shouldProcessExtensionsBeforeMembers =
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
if (shouldProcessExtensionsBeforeMembers) { if (shouldProcessExtensionsBeforeMembers) {
@@ -145,7 +142,6 @@ class FirTowerResolver(
session, components, topLevelScope, extensionReceiver = implicitReceiverValue, extensionsOnly = true session, components, topLevelScope, extensionReceiver = implicitReceiverValue, extensionsOnly = true
), info, TowerGroup.TopPrioritized(index).Implicit(depth) ), info, TowerGroup.TopPrioritized(index).Implicit(depth)
) )
if (collector.isSuccess()) return collector
} }
} }
} }
@@ -155,7 +151,6 @@ class FirTowerResolver(
val result = manager.processLevel( val result = manager.processLevel(
ScopeTowerLevel(session, components, localScope), info, TowerGroup.Local(index) ScopeTowerLevel(session, components, localScope), info, TowerGroup.Local(index)
) )
if (collector.isSuccess()) return collector
if (result != ProcessorAction.NONE) { if (result != ProcessorAction.NONE) {
nonEmptyLocalScopes += localScope nonEmptyLocalScopes += localScope
} }
@@ -171,7 +166,6 @@ class FirTowerResolver(
session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession
), info, parentGroup.Member ), info, parentGroup.Member
) )
if (collector.isSuccess()) return collector
if (implicitResult == ProcessorAction.NONE) { if (implicitResult == ProcessorAction.NONE) {
implicitReceiverValuesWithEmptyScopes += implicitReceiverValue implicitReceiverValuesWithEmptyScopes += implicitReceiverValue
} }
@@ -181,7 +175,6 @@ class FirTowerResolver(
session, components, localScope, extensionReceiver = implicitReceiverValue session, components, localScope, extensionReceiver = implicitReceiverValue
), info, parentGroup.Local(localIndex) ), info, parentGroup.Local(localIndex)
) )
if (collector.isSuccess()) return collector
} }
for ((implicitDispatchReceiverValue, usable, dispatchDepth) in implicitReceivers) { for ((implicitDispatchReceiverValue, usable, dispatchDepth) in implicitReceivers) {
if (!usable) continue if (!usable) continue
@@ -195,7 +188,6 @@ class FirTowerResolver(
scopeSession = components.scopeSession scopeSession = components.scopeSession
), info, parentGroup.Implicit(dispatchDepth) ), info, parentGroup.Implicit(dispatchDepth)
) )
if (collector.isSuccess()) return collector
} }
for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) { for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) {
if (topLevelScope in emptyTopLevelScopes) continue if (topLevelScope in emptyTopLevelScopes) continue
@@ -204,7 +196,6 @@ class FirTowerResolver(
session, components, topLevelScope, extensionReceiver = implicitReceiverValue session, components, topLevelScope, extensionReceiver = implicitReceiverValue
), info, parentGroup.Top(topIndex) ), info, parentGroup.Top(topIndex)
) )
if (collector.isSuccess()) return collector
if (result == ProcessorAction.NONE) { if (result == ProcessorAction.NONE) {
emptyTopLevelScopes += topLevelScope emptyTopLevelScopes += topLevelScope
} }
@@ -232,19 +223,15 @@ class FirTowerResolver(
manager.processLevel( manager.processLevel(
ScopeTowerLevel(session, components, topLevelScope), info, TowerGroup.Top(index) ScopeTowerLevel(session, components, topLevelScope), info, TowerGroup.Top(index)
) )
if (collector.isSuccess()) return collector
} }
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
return collector
} }
private fun runResolverForExpressionReceiver( private suspend fun runResolverForExpressionReceiver(
info: CallInfo, info: CallInfo,
collector: CandidateCollector, collector: CandidateCollector,
receiver: FirExpression, receiver: FirExpression,
manager: TowerResolveManager manager: TowerResolveManager
): CandidateCollector { ) {
val explicitReceiverValue = ExpressionReceiverValue(receiver) val explicitReceiverValue = ExpressionReceiverValue(receiver)
val shouldProcessExtensionsBeforeMembers = val shouldProcessExtensionsBeforeMembers =
@@ -257,7 +244,6 @@ class FirTowerResolver(
session, components, topLevelScope, extensionReceiver = explicitReceiverValue, extensionsOnly = true session, components, topLevelScope, extensionReceiver = explicitReceiverValue, extensionsOnly = true
), info, TowerGroup.TopPrioritized(index), ExplicitReceiverKind.EXTENSION_RECEIVER ), info, TowerGroup.TopPrioritized(index), ExplicitReceiverKind.EXTENSION_RECEIVER
) )
if (collector.isSuccess()) return collector
} }
} }
@@ -266,40 +252,33 @@ class FirTowerResolver(
session, components, dispatchReceiver = explicitReceiverValue, scopeSession = components.scopeSession session, components, dispatchReceiver = explicitReceiverValue, scopeSession = components.scopeSession
), info, TowerGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER ), info, TowerGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER
) )
if (collector.isSuccess()) return collector
val shouldProcessExplicitReceiverScopeOnly = val shouldProcessExplicitReceiverScopeOnly =
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
if (shouldProcessExplicitReceiverScopeOnly) { if (shouldProcessExplicitReceiverScopeOnly) {
// Special case (integer literal type) // Special case (integer literal type)
return collector return
} }
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>() val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
for ((index, localScope) in localScopes.withIndex()) { for ((index, localScope) in localScopes.withIndex()) {
manager.enqueueLevelForInvoke(
ScopeTowerLevel(session, components, localScope), info, TowerGroup.Local(index),
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
val result = manager.processLevel( val result = manager.processLevel(
ScopeTowerLevel( ScopeTowerLevel(
session, components, localScope, extensionReceiver = explicitReceiverValue session, components, localScope, extensionReceiver = explicitReceiverValue
), info, TowerGroup.Local(index), ExplicitReceiverKind.EXTENSION_RECEIVER ), info, TowerGroup.Local(index), ExplicitReceiverKind.EXTENSION_RECEIVER
) )
if (collector.isSuccess()) return collector
if (result != ProcessorAction.NONE) { if (result != ProcessorAction.NONE) {
nonEmptyLocalScopes += localScope nonEmptyLocalScopes += localScope
} }
manager.processLevelForPropertyWithInvoke(
ScopeTowerLevel(session, components, localScope), info, TowerGroup.Local(index)
)
} }
for ((implicitReceiverValue, usableAsValue, depth) in implicitReceivers) { for ((implicitReceiverValue, usableAsValue, depth) in implicitReceivers) {
if (!usableAsValue) continue if (!usableAsValue) continue
// NB: companions are processed via implicitReceiverValues! // NB: companions are processed via implicitReceiverValues!
val parentGroup = TowerGroup.Implicit(depth) val parentGroup = TowerGroup.Implicit(depth)
manager.enqueueLevelForInvoke(
MemberScopeTowerLevel(
session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession
), info, parentGroup.Member, InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
manager.processLevel( manager.processLevel(
MemberScopeTowerLevel( MemberScopeTowerLevel(
session, components, session, components,
@@ -307,137 +286,138 @@ class FirTowerResolver(
scopeSession = components.scopeSession scopeSession = components.scopeSession
), info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER ), info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER
) )
if (collector.isSuccess()) return collector manager.processLevelForPropertyWithInvoke(
MemberScopeTowerLevel(
session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession
), info, parentGroup.Member
)
for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) { for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) {
manager.enqueueLevelForInvoke( manager.processLevelForPropertyWithInvoke(
ScopeTowerLevel( ScopeTowerLevel(
session, components, localScope, extensionReceiver = implicitReceiverValue session, components, localScope, extensionReceiver = implicitReceiverValue
), info, parentGroup.Local(localIndex), InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION ), info, parentGroup.Local(localIndex)
) )
} }
for ((implicitDispatchReceiverValue, usable, dispatchDepth) in implicitReceivers) { for ((implicitDispatchReceiverValue, usable, dispatchDepth) in implicitReceivers) {
if (!usable) continue if (!usable) continue
manager.enqueueLevelForInvoke( manager.processLevelForPropertyWithInvoke(
MemberScopeTowerLevel( MemberScopeTowerLevel(
session, session,
components, components,
dispatchReceiver = implicitDispatchReceiverValue, dispatchReceiver = implicitDispatchReceiverValue,
extensionReceiver = implicitReceiverValue, extensionReceiver = implicitReceiverValue,
scopeSession = components.scopeSession scopeSession = components.scopeSession
), info, parentGroup.Implicit(dispatchDepth), ), info, parentGroup.Implicit(dispatchDepth)
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
) )
} }
for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) { for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) {
manager.enqueueLevelForInvoke( manager.processLevelForPropertyWithInvoke(
ScopeTowerLevel( ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = implicitReceiverValue session, components, topLevelScope, extensionReceiver = implicitReceiverValue
), info, parentGroup.Top(topIndex), InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION ), info, parentGroup.Top(topIndex)
) )
} }
} }
for ((index, topLevelScope) in topLevelScopes.withIndex()) { for ((index, topLevelScope) in topLevelScopes.withIndex()) {
manager.enqueueLevelForInvoke(
ScopeTowerLevel(session, components, topLevelScope), info, TowerGroup.Top(index),
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
manager.processLevel( manager.processLevel(
ScopeTowerLevel( ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = explicitReceiverValue session, components, topLevelScope, extensionReceiver = explicitReceiverValue
), info, TowerGroup.Top(index), ExplicitReceiverKind.EXTENSION_RECEIVER ), info, TowerGroup.Top(index), ExplicitReceiverKind.EXTENSION_RECEIVER
) )
if (collector.isSuccess()) return collector manager.processLevelForPropertyWithInvoke(
ScopeTowerLevel(session, components, topLevelScope), info, TowerGroup.Top(index)
)
} }
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
return collector
} }
private fun runResolverForSuperReceiver( private suspend fun runResolverForSuperReceiver(
info: CallInfo, info: CallInfo,
collector: CandidateCollector, collector: CandidateCollector,
superTypeRef: FirTypeRef, superTypeRef: FirTypeRef,
manager: TowerResolveManager manager: TowerResolveManager
): CandidateCollector { ) {
val scope = when (superTypeRef) { val scope = when (superTypeRef) {
is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession) is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession)
is FirComposedSuperTypeRef -> FirCompositeScope( is FirComposedSuperTypeRef -> FirCompositeScope(
superTypeRef.superTypeRefs.mapNotNullTo(mutableListOf()) { it.type.scope(session, components.scopeSession) } superTypeRef.superTypeRefs.mapNotNullTo(mutableListOf()) { it.type.scope(session, components.scopeSession) }
) )
else -> null else -> null
} ?: return collector } ?: return
manager.processLevel( manager.processLevel(
ScopeTowerLevel( ScopeTowerLevel(
session, components, scope session, components, scope
), info, TowerGroup.Member, explicitReceiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER ), info, TowerGroup.Member, explicitReceiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER
) )
return collector
} }
internal fun enqueueResolverForInvoke( internal suspend fun runResolverForInvoke(
info: CallInfo, info: CallInfo,
invokeReceiverValue: ExpressionReceiverValue, invokeReceiverValue: ExpressionReceiverValue,
manager: TowerResolveManager manager: TowerResolveManager
) { ) {
manager.enqueueLevelForInvoke( manager.processLevel(
MemberScopeTowerLevel( MemberScopeTowerLevel(
session, components, dispatchReceiver = invokeReceiverValue, scopeSession = components.scopeSession session, components, dispatchReceiver = invokeReceiverValue, scopeSession = components.scopeSession
), info, TowerGroup.Member, ),
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER, info, TowerGroup.Member,
ExplicitReceiverKind.DISPATCH_RECEIVER ExplicitReceiverKind.DISPATCH_RECEIVER,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER
) )
for ((index, localScope) in localScopes.withIndex()) { for ((index, localScope) in localScopes.withIndex()) {
manager.enqueueLevelForInvoke( manager.processLevel(
ScopeTowerLevel( ScopeTowerLevel(
session, components, localScope, extensionReceiver = invokeReceiverValue session, components, localScope, extensionReceiver = invokeReceiverValue
), info, TowerGroup.Local(index), ),
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER, info, TowerGroup.Local(index),
ExplicitReceiverKind.EXTENSION_RECEIVER ExplicitReceiverKind.EXTENSION_RECEIVER,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER
) )
} }
for ((implicitReceiverValue, usable, depth) in implicitReceivers) { for ((implicitReceiverValue, usable, depth) in implicitReceivers) {
if (!usable) continue if (!usable) continue
// NB: companions are processed via implicitReceiverValues! // NB: companions are processed via implicitReceiverValues!
val parentGroup = TowerGroup.Implicit(depth) val parentGroup = TowerGroup.Implicit(depth)
manager.enqueueLevelForInvoke( manager.processLevel(
MemberScopeTowerLevel( MemberScopeTowerLevel(
session, components, session, components,
dispatchReceiver = implicitReceiverValue, extensionReceiver = invokeReceiverValue, dispatchReceiver = implicitReceiverValue, extensionReceiver = invokeReceiverValue,
scopeSession = components.scopeSession scopeSession = components.scopeSession
), info, parentGroup.Member, ), info, parentGroup.Member,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER, ExplicitReceiverKind.EXTENSION_RECEIVER,
ExplicitReceiverKind.EXTENSION_RECEIVER InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER
) )
} }
for ((index, topLevelScope) in topLevelScopes.withIndex()) { for ((index, topLevelScope) in topLevelScopes.withIndex()) {
manager.enqueueLevelForInvoke( manager.processLevel(
ScopeTowerLevel( ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = invokeReceiverValue session, components, topLevelScope, extensionReceiver = invokeReceiverValue
), info, TowerGroup.Top(index), ), info, TowerGroup.Top(index),
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER, ExplicitReceiverKind.EXTENSION_RECEIVER,
ExplicitReceiverKind.EXTENSION_RECEIVER InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER
) )
} }
} }
// Here we already know extension receiver for invoke, and it's stated in info as first argument // Here we already know extension receiver for invoke, and it's stated in info as first argument
internal fun enqueueResolverForBuiltinInvokeExtensionWithExplicitArgument( internal suspend fun runResolverForBuiltinInvokeExtensionWithExplicitArgument(
info: CallInfo, info: CallInfo,
invokeReceiverValue: ExpressionReceiverValue, invokeReceiverValue: ExpressionReceiverValue,
manager: TowerResolveManager manager: TowerResolveManager
) { ) {
manager.enqueueLevelForInvoke( manager.processLevel(
MemberScopeTowerLevel( MemberScopeTowerLevel(
session, components, dispatchReceiver = invokeReceiverValue, session, components, dispatchReceiver = invokeReceiverValue,
scopeSession = components.scopeSession scopeSession = components.scopeSession
), info, TowerGroup.Member, ), info, TowerGroup.Member,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER, ExplicitReceiverKind.DISPATCH_RECEIVER,
ExplicitReceiverKind.DISPATCH_RECEIVER InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER
) )
} }
// Here we don't know extension receiver for invoke, assuming it's one of implicit receivers // Here we don't know extension receiver for invoke, assuming it's one of implicit receivers
internal fun enqueueResolverForBuiltinInvokeExtensionWithImplicitArgument( internal suspend fun runResolverForBuiltinInvokeExtensionWithImplicitArgument(
info: CallInfo, info: CallInfo,
invokeReceiverValue: ExpressionReceiverValue, invokeReceiverValue: ExpressionReceiverValue,
manager: TowerResolveManager manager: TowerResolveManager
@@ -445,15 +425,15 @@ class FirTowerResolver(
for ((implicitReceiverValue, usable, depth) in implicitReceivers) { for ((implicitReceiverValue, usable, depth) in implicitReceivers) {
if (!usable) continue if (!usable) continue
val parentGroup = TowerGroup.Implicit(depth) val parentGroup = TowerGroup.Implicit(depth)
manager.enqueueLevelForInvoke( manager.processLevel(
MemberScopeTowerLevel( MemberScopeTowerLevel(
session, components, dispatchReceiver = invokeReceiverValue, session, components, dispatchReceiver = invokeReceiverValue,
extensionReceiver = implicitReceiverValue, extensionReceiver = implicitReceiverValue,
implicitExtensionInvokeMode = true, implicitExtensionInvokeMode = true,
scopeSession = components.scopeSession scopeSession = components.scopeSession
), info, parentGroup.InvokeExtension, ), info, parentGroup.InvokeExtension,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER, ExplicitReceiverKind.DISPATCH_RECEIVER,
ExplicitReceiverKind.DISPATCH_RECEIVER InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER
) )
} }
} }
@@ -482,19 +462,23 @@ class FirTowerResolver(
} }
} }
return when (val receiver = info.explicitReceiver) {
is FirResolvedQualifier -> runResolverForQualifierReceiver(info, collector, receiver, manager)
null -> runResolverForNoReceiver(info, collector, manager) when (val receiver = info.explicitReceiver) {
else -> { is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, collector, receiver, manager) }
null -> manager.enqueueResolverTask { runResolverForNoReceiver(info, collector, manager) }
else -> run {
if (receiver is FirQualifiedAccessExpression) { if (receiver is FirQualifiedAccessExpression) {
val calleeReference = receiver.calleeReference val calleeReference = receiver.calleeReference
if (calleeReference is FirSuperReference) { if (calleeReference is FirSuperReference) {
return runResolverForSuperReceiver(info, collector, receiver.typeRef, manager) return@run manager.enqueueResolverTask { runResolverForSuperReceiver(info, collector, receiver.typeRef, manager) }
} }
} }
runResolverForExpressionReceiver(info, collector, receiver, manager) manager.enqueueResolverTask { runResolverForExpressionReceiver(info, collector, receiver, manager) }
} }
} }
manager.runTasks()
return collector
} }
fun reset() { fun reset() {
@@ -1,25 +0,0 @@
/*
* Copyright 2010-2020 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 org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
internal class TowerInvokeResolveQuery(
val towerLevel: SessionBasedTowerLevel,
val callInfo: CallInfo,
val explicitReceiverKind: ExplicitReceiverKind,
val group: TowerGroup,
val mode: InvokeResolveMode
) : Comparable<TowerInvokeResolveQuery> {
override fun compareTo(other: TowerInvokeResolveQuery): Int {
return group.compareTo(other.group)
}
}
enum class InvokeResolveMode {
IMPLICIT_CALL_ON_GIVEN_RECEIVER,
RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
}
@@ -22,11 +22,11 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.* import java.util.*
import kotlin.coroutines.*
class TowerResolveManager internal constructor(private val towerResolver: FirTowerResolver) { class TowerResolveManager internal constructor(private val towerResolver: FirTowerResolver) {
private val queue = PriorityQueue<TowerInvokeResolveQuery>()
private var group = TowerGroup.Start private val queue = PriorityQueue<SuspendedResolverTask>()
lateinit var candidateFactory: CandidateFactory lateinit var candidateFactory: CandidateFactory
@@ -199,26 +199,33 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
invokeOnGivenReceiverCandidateFactory = CandidateFactory(towerResolver.components, invokeFunctionInfo) invokeOnGivenReceiverCandidateFactory = CandidateFactory(towerResolver.components, invokeFunctionInfo)
when { when {
invokeBuiltinExtensionMode -> { invokeBuiltinExtensionMode -> {
towerResolver.enqueueResolverForBuiltinInvokeExtensionWithExplicitArgument( enqueueResolverTask {
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager towerResolver.runResolverForBuiltinInvokeExtensionWithExplicitArgument(
) invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
)
}
} }
useImplicitReceiverAsBuiltinInvokeArgument -> { useImplicitReceiverAsBuiltinInvokeArgument -> {
towerResolver.enqueueResolverForBuiltinInvokeExtensionWithImplicitArgument( enqueueResolverTask {
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager towerResolver.runResolverForBuiltinInvokeExtensionWithImplicitArgument(
) invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
towerResolver.enqueueResolverForInvoke( )
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager }
) enqueueResolverTask {
towerResolver.runResolverForInvoke(
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
)
}
} }
else -> { else -> {
towerResolver.enqueueResolverForInvoke( enqueueResolverTask {
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager towerResolver.runResolverForInvoke(
) invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
)
}
} }
} }
} }
processQueuedLevelsForInvoke()
} }
} }
CallKind.CallableReference -> { CallKind.CallableReference -> {
@@ -260,47 +267,85 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
fun reset() { fun reset() {
queue.clear() queue.clear()
group = TowerGroup.Start
} }
fun processLevel(
private suspend fun suspendResolverTask(group: TowerGroup) = suspendCoroutine<Unit> { queue += SuspendedResolverTask(it, group) }
private suspend fun requestGroup(requested: TowerGroup) {
val peeked = queue.peek()
// Task ordering should be FIFO
// Here, if peeked have equal group it means that it came first to this function, so should be processed before us
if (peeked != null && peeked.group <= requested) {
suspendResolverTask(requested)
}
}
private suspend fun stopResolverTask(): Nothing = suspendCoroutine { }
suspend fun processLevel(
towerLevel: SessionBasedTowerLevel, towerLevel: SessionBasedTowerLevel,
callInfo: CallInfo, callInfo: CallInfo,
group: TowerGroup, group: TowerGroup,
explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
invokeResolveMode: InvokeResolveMode? = null
): ProcessorAction { ): ProcessorAction {
assert(group > this.group) { requestGroup(group)
"Incorrect TowerGroup processing order (c) Mikhail Glukhikh"
}
this.group = group
val result = with(LevelHandler(callInfo, explicitReceiverKind, group)) { val result = with(LevelHandler(callInfo, explicitReceiverKind, group)) {
towerLevel.handleLevel() towerLevel.handleLevel(invokeResolveMode)
} }
processQueuedLevelsForInvoke()
if (resultCollector.isSuccess()) stopResolverTask()
return result return result
} }
fun enqueueLevelForInvoke(
suspend fun processLevelForPropertyWithInvoke(
towerLevel: SessionBasedTowerLevel, towerLevel: SessionBasedTowerLevel,
callInfo: CallInfo, callInfo: CallInfo,
group: TowerGroup, group: TowerGroup,
mode: InvokeResolveMode,
explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
) { ) {
if (callInfo.callKind == CallKind.Function) { if (callInfo.callKind == CallKind.Function) {
queue.add(TowerInvokeResolveQuery(towerLevel, callInfo, explicitReceiverKind, group, mode)) processLevel(towerLevel, callInfo, group, explicitReceiverKind, InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION)
} }
} }
fun processQueuedLevelsForInvoke(groupLimit: TowerGroup = this.group) { data class SuspendedResolverTask(val continuation: Continuation<Unit>, val group: TowerGroup): Comparable<SuspendedResolverTask> {
while (queue.isNotEmpty()) { override fun compareTo(other: SuspendedResolverTask): Int {
if (queue.peek().group > groupLimit) { return group.compareTo(other.group)
break
}
val query = queue.poll()
with(LevelHandler(query.callInfo, query.explicitReceiverKind, query.group)) {
query.towerLevel.handleLevel(invokeResolveMode = query.mode)
}
} }
} }
fun enqueueResolverTask(group: TowerGroup = TowerGroup.Start, task: suspend () -> Unit) {
val continuation = task.createCoroutine(
object : Continuation<Unit> {
override val context: CoroutineContext
get() = EmptyCoroutineContext
override fun resumeWith(result: Result<Unit>) {
result.getOrThrow()
}
}
)
queue += SuspendedResolverTask(continuation, group)
}
fun runTasks() {
while (queue.isNotEmpty()) {
queue.poll().continuation.resume(Unit)
if (resultCollector.isSuccess()) return
}
}
}
enum class InvokeResolveMode {
IMPLICIT_CALL_ON_GIVEN_RECEIVER,
RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
} }
@@ -20,7 +20,7 @@ val D.attr: B
fun main() { fun main() {
val b = D() val b = D()
b.<!AMBIGUITY!>attr<!> {} // overload resolution ambiguity b.attr {} // overload resolution ambiguity
val d = b.attr val d = b.attr
d {} // no error d {} // no error