[FIR] Refactoring: create consumer inside tower resolver

This commit is contained in:
Mikhail Glukhikh
2020-01-10 15:54:59 +03:00
parent 30e339a2d7
commit 9e0db86900
3 changed files with 62 additions and 88 deletions
@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
class FirCallResolver(
components: BodyResolveComponents,
@@ -118,7 +117,6 @@ class FirCallResolver(
val explicitReceiver = functionCall.explicitReceiver
val arguments = functionCall.arguments
val typeArguments = functionCall.typeArguments
val name = functionCall.calleeReference.name
val info = CallInfo(
CallKind.Function,
@@ -131,13 +129,10 @@ class FirCallResolver(
transformer.components.implicitReceiverStack
)
towerResolver.reset()
val consumer = createFunctionConsumer(session, name, info, this, towerResolver.collector, towerResolver)
val result = towerResolver.runResolver(
consumer,
implicitReceiverStack.receiversAsReversed(),
shouldProcessExtensionsBeforeMembers = name in HIDES_MEMBERS_NAME_LIST,
shouldProcessExplicitReceiverScopeOnly = explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
functionCall.calleeReference.name,
info
)
val bestCandidates = result.bestCandidates()
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
@@ -168,14 +163,11 @@ class FirCallResolver(
transformer.components.implicitReceiverStack
)
towerResolver.reset()
val consumer = createVariableAndObjectConsumer(
session,
val result = towerResolver.runResolver(
implicitReceiverStack.receiversAsReversed(),
callee.name,
info, this,
towerResolver.collector
info
)
val result = towerResolver.runResolver(consumer, implicitReceiverStack.receiversAsReversed())
val bestCandidates = result.bestCandidates()
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
@@ -247,15 +239,17 @@ class FirCallResolver(
val coneSubstitutor = constraintSystemBuilder.buildCurrentSubstitutor() as ConeSubstitutor
val expectedType = resolvedCallableReferenceAtom.expectedType?.let(coneSubstitutor::substituteOrSelf)
val result = CandidateCollector(this, resolutionStageRunner)
val consumer =
createCallableReferencesConsumerForLHS(
callableReferenceAccess, lhs,
result, expectedType,
constraintSystemBuilder
)
towerResolver.runResolver(consumer, implicitReceiverStack.receiversAsReversed())
val info = createCallableReferencesInfoForLHS(
callableReferenceAccess, lhs,
expectedType, constraintSystemBuilder
)
// No reset here!
val result = towerResolver.runResolver(
implicitReceiverStack.receiversAsReversed(),
callableReferenceAccess.calleeReference.name,
info,
collector = CandidateCollector(this, resolutionStageRunner)
)
val bestCandidates = result.bestCandidates()
val noSuccessfulCandidates = result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED
val reducedCandidates = if (noSuccessfulCandidates) {
@@ -336,79 +330,29 @@ class FirCallResolver(
return call.transformCalleeReference(StoreNameReference, nameReference) as T
}
private fun createCallableReferencesConsumerForLHS(
private fun createCallableReferencesInfoForLHS(
callableReferenceAccess: FirCallableReferenceAccess,
lhs: DoubleColonLHS?,
resultCollector: CandidateCollector,
expectedType: ConeKotlinType?,
outerConstraintSystemBuilder: ConstraintSystemBuilder?
): TowerDataConsumer {
val name = callableReferenceAccess.calleeReference.name
return when (lhs) {
is DoubleColonLHS.Expression, null -> createCallableReferencesConsumerForReceiver(
name, resultCollector, callableReferenceAccess.explicitReceiver, expectedType, outerConstraintSystemBuilder,
lhs
)
is DoubleColonLHS.Type -> createCallableReferencesConsumerForReceivers(
name,
resultCollector,
expectedType,
outerConstraintSystemBuilder,
lhs,
FirExpressionStub(callableReferenceAccess.source).apply { replaceTypeRef(FirResolvedTypeRefImpl(null, lhs.type)) },
callableReferenceAccess.explicitReceiver
)
}
}
private fun createCallableReferencesConsumerForReceivers(
name: Name,
resultCollector: CandidateCollector,
expectedType: ConeKotlinType?,
outerConstraintSystemBuilder: ConstraintSystemBuilder?,
lhs: DoubleColonLHS?,
vararg receivers: FirExpression?
): TowerDataConsumer {
if (receivers.size == 1) {
return createCallableReferencesConsumerForReceiver(
name, resultCollector, receivers[0], expectedType, outerConstraintSystemBuilder, lhs
)
}
return PrioritizedTowerDataConsumer(
resultCollector,
*Array(receivers.size) { index ->
createCallableReferencesConsumerForReceiver(
name, resultCollector, receivers[index], expectedType, outerConstraintSystemBuilder, lhs
)
}
)
}
private fun createCallableReferencesConsumerForReceiver(
name: Name,
resultCollector: CandidateCollector,
receiver: FirExpression?,
expectedType: ConeKotlinType?,
outerConstraintSystemBuilder: ConstraintSystemBuilder?,
lhs: DoubleColonLHS?
): TowerDataConsumer {
val info = CallInfo(
): CallInfo {
return CallInfo(
CallKind.CallableReference,
receiver,
callableReferenceAccess.explicitReceiver,
emptyList(),
false,
emptyList(),
session,
file,
transformer.components.implicitReceiverStack,
// Additional things for callable reference resolve
expectedType,
outerConstraintSystemBuilder,
lhs
lhs,
stubReceiver = if (lhs !is DoubleColonLHS.Type) null else FirExpressionStub(callableReferenceAccess.source).apply {
replaceTypeRef(FirResolvedTypeRefImpl(null, lhs.type))
}
)
return createCallableReferencesConsumer(session, name, info, this, resultCollector)
}
private fun createResolvedNamedReference(
@@ -36,10 +36,11 @@ class CallInfo(
val containingFile: FirFile,
val implicitReceiverStack: ImplicitReceiverStack,
// Three properties for callable references only
// Four properties for callable references only
val expectedType: ConeKotlinType? = null,
val outerCSBuilder: ConstraintSystemBuilder? = null,
val lhs: DoubleColonLHS? = null
val lhs: DoubleColonLHS? = null,
val stubReceiver: FirExpression? = null
) {
val argumentCount get() = arguments.size
@@ -14,6 +14,10 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NONE
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
enum class TowerDataKind {
EMPTY, // Corresponds to stub tower level which is replaced by receiver-related level
@@ -199,13 +203,38 @@ class FirTowerResolver(
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue<*>>
fun runResolver(
consumer: TowerDataConsumer,
implicitReceiverValues: List<ImplicitReceiverValue<*>>,
shouldProcessExtensionsBeforeMembers: Boolean = false,
shouldProcessExplicitReceiverScopeOnly: Boolean = false
implicitReceiverValues: List<ImplicitReceiverValue<*>>, name: Name, info: CallInfo,
collector: CandidateCollector = this.collector
): CandidateCollector {
this.implicitReceiverValues = implicitReceiverValues
towerDataConsumer = consumer
towerDataConsumer = when (info.callKind) {
CallKind.VariableAccess -> {
createVariableAndObjectConsumer(session, name, info, components, collector)
}
CallKind.Function -> {
createFunctionConsumer(session, name, info, components, collector, this)
}
CallKind.CallableReference -> {
if (info.stubReceiver == null) {
createCallableReferencesConsumer(session, name, info, components, collector)
} else {
PrioritizedTowerDataConsumer(
collector,
createCallableReferencesConsumer(
session, name, info.replaceExplicitReceiver(info.stubReceiver), components, collector
),
createCallableReferencesConsumer(
session, name, info, components, collector
)
)
}
}
else -> throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
}
val shouldProcessExtensionsBeforeMembers =
info.callKind == CallKind.Function && name in HIDES_MEMBERS_NAME_LIST
val shouldProcessExplicitReceiverScopeOnly =
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
var group = 0