FIR: Simplify delegating constructors call resolution

This commit is contained in:
Denis Zharkov
2020-07-30 16:46:47 +03:00
parent 8b71f5e558
commit 6a16d6a246
4 changed files with 30 additions and 75 deletions
@@ -7,7 +7,11 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.types.AbstractTypeChecker
class FirTowerResolver(
private val components: BodyResolveComponents,
@@ -32,14 +36,35 @@ class FirTowerResolver(
fun runResolverForDelegatingConstructor(
info: CallInfo,
constructedType: ConeClassLikeType,
constructedType: ConeClassLikeType
): CandidateCollector {
val candidateFactoriesAndCollectors = buildCandidateFactoriesAndCollectors(info, collector)
val outerType = components.outerClassManager.outerType(constructedType)
val scope = constructedType.scope(components.session, components.scopeSession) ?: return collector
val towerResolverSession = FirTowerResolverSession(components, manager, candidateFactoriesAndCollectors, info)
towerResolverSession.runResolutionForDelegatingConstructor(info, constructedType)
val dispatchReceiver =
if (outerType != null)
components.implicitReceiverStack.receiversAsReversed().drop(1).firstOrNull {
AbstractTypeChecker.isSubtypeOf(components.session.typeContext, it.type, outerType)
} ?: return collector // TODO: report diagnostic about not-found receiver
else
null
val candidateFactory = CandidateFactory(components, info)
val resultCollector = collector
scope.processDeclaredConstructors {
resultCollector.consumeCandidate(
TowerGroup.Member,
candidateFactory.createCandidate(
it,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
dispatchReceiver,
implicitExtensionReceiverValue = null,
builtInExtensionFunctionReceiverValue = null
)
)
}
manager.runTasks()
return collector
}
@@ -22,12 +22,10 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.util.OperatorNameConventions
class FirTowerResolverSession internal constructor(
@@ -66,13 +64,6 @@ class FirTowerResolverSession internal constructor(
}
}
fun runResolutionForDelegatingConstructor(
info: CallInfo,
constructedType: ConeClassLikeType
) {
manager.enqueueResolverTask { runResolverForDelegatingConstructorCall(info, constructedType) }
}
fun runResolution(info: CallInfo) {
when (val receiver = info.explicitReceiver) {
is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver) }
@@ -140,9 +131,6 @@ class FirTowerResolverSession internal constructor(
extensionReceiver, extensionsOnly, includeInnerConstructors
)
private fun FirScope.toConstructorScopeTowerLevel(dispatchReceiver: ImplicitReceiver?): ConstructorScopeTowerLevel =
ConstructorScopeTowerLevel(session, this, dispatchReceiver?.receiver)
private fun ReceiverValue.toMemberScopeTowerLevel(
extensionReceiver: ReceiverValue? = null,
implicitExtensionInvokeMode: Boolean = false
@@ -213,27 +201,6 @@ class FirTowerResolverSession internal constructor(
}
}
private suspend fun runResolverForDelegatingConstructorCall(
info: CallInfo,
constructedType: ConeClassLikeType
) {
val outerType = components.outerClassManager.outerType(constructedType)
val scope = constructedType.scope(session, components.scopeSession) ?: return
val dispatchReceiver =
if (outerType != null)
implicitReceivers.drop(1).firstOrNull {
AbstractTypeChecker.isSubtypeOf(components.session.typeContext, it.receiver.type, outerType)
} ?: return // TODO: report diagnostic about not-found receiver
else
null
processLevel(
scope.toConstructorScopeTowerLevel(dispatchReceiver),
info, TowerGroup.Member
)
}
private suspend fun runResolverForNoReceiver(
info: CallInfo
) {
@@ -122,9 +122,6 @@ internal class TowerLevelHandler {
towerLevel.processFunctionsAndProperties(info.name, processor)
}
}
CallKind.DelegatingConstructorCall -> {
towerLevel.processElementsByNameAndStoreResult(TowerScopeLevel.Token.ConstructorsForDelegationCall, info.name, processor)
}
else -> {
throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
}
@@ -35,7 +35,6 @@ interface TowerScopeLevel {
sealed class Token<out T : AbstractFirBasedSymbol<*>> {
object Properties : Token<FirVariableSymbol<*>>()
object Functions : Token<FirFunctionSymbol<*>>()
object ConstructorsForDelegationCall : Token<FirConstructorSymbol>()
object Objects : Token<AbstractFirBasedSymbol<*>>()
}
@@ -156,7 +155,6 @@ class MemberScopeTowerLevel(
consumer(it as T)
}
}
TowerScopeLevel.Token.ConstructorsForDelegationCall -> error("ConstructorsForDelegationCall should be handled via ConstructorScopeTowerLevel")
}
}
@@ -263,38 +261,6 @@ class ScopeTowerLevel(
implicitExtensionReceiverValue = null
)
}
TowerScopeLevel.Token.ConstructorsForDelegationCall -> {
throw AssertionError("Should not be here")
}
}
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
}
}
class ConstructorScopeTowerLevel(
session: FirSession,
private val scope: FirScope,
private val dispatchReceiver: ImplicitReceiverValue<*>?,
) : SessionBasedTowerLevel(session) {
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
token: TowerScopeLevel.Token<T>,
name: Name,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction {
var empty = true
when (token) {
TowerScopeLevel.Token.ConstructorsForDelegationCall -> scope.processDeclaredConstructors { candidate ->
empty = false
@Suppress("UNCHECKED_CAST")
processor.consumeCandidate(
candidate as T,
dispatchReceiverValue = dispatchReceiver,
implicitExtensionReceiverValue = null
)
}
else -> {
throw AssertionError("Should not be here: token = $token")
}
}
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
}