FIR: Simplify and clarify contracts in FirInvokeResolveTowerExtension

This commit is contained in:
Denis.Zharkov
2022-02-18 18:28:20 +03:00
committed by teamcity
parent f7371816de
commit 150f951fb2
@@ -31,15 +31,11 @@ internal class FirInvokeResolveTowerExtension(
fun enqueueResolveTasksForQualifier(info: CallInfo, receiver: FirResolvedQualifier) { fun enqueueResolveTasksForQualifier(info: CallInfo, receiver: FirResolvedQualifier) {
if (info.callKind != CallKind.Function) return if (info.callKind != CallKind.Function) return
enqueueBothInvokeReceiverTasks( enqueueResolveForExplicitReceiver(
info, info
invokeAction = { task, receiverInfo -> ) { task, receiverInfo ->
task.runResolverForQualifierReceiver(receiverInfo, receiver) task.runResolverForQualifierReceiver(receiverInfo, receiver)
}, }
invokeExtensionAction = { task, receiverInfo ->
task.runResolverForNoReceiver(receiverInfo)
}
)
} }
fun enqueueResolveTasksForNoReceiver(info: CallInfo) { fun enqueueResolveTasksForNoReceiver(info: CallInfo) {
@@ -68,24 +64,24 @@ internal class FirInvokeResolveTowerExtension(
fun enqueueResolveTasksForExpressionReceiver(info: CallInfo, receiver: FirExpression) { fun enqueueResolveTasksForExpressionReceiver(info: CallInfo, receiver: FirExpression) {
if (info.callKind != CallKind.Function) return if (info.callKind != CallKind.Function) return
enqueueBothInvokeReceiverTasks( enqueueResolveForExplicitReceiver(
info, info
invokeAction = { task, receiverInfo -> ) { task, receiverInfo ->
task.runResolverForExpressionReceiver(receiverInfo, receiver) task.runResolverForExpressionReceiver(receiverInfo, receiver)
}, }
invokeExtensionAction = { task, receiverInfo ->
task.runResolverForNoReceiver(receiverInfo)
}
)
} }
private inline fun enqueueBothInvokeReceiverTasks( /**
* It's whether Qualifier.f() or expressionReceiver.f(), later we name it as "x.f()"
*
* @param originalCallInfo describes whole "x.f()"
* @param invokeAction runs the process of looking for the receiver "x.f" depending on the kind of "x" (qualifier or expression)
*/
private inline fun enqueueResolveForExplicitReceiver(
originalCallInfo: CallInfo, originalCallInfo: CallInfo,
crossinline invokeAction: suspend (FirTowerResolveTask, CallInfo) -> Unit, crossinline invokeAction: suspend (FirTowerResolveTask, CallInfo) -> Unit
crossinline invokeExtensionAction: suspend (FirTowerResolveTask, CallInfo) -> Unit
) { ) {
val invokeReceiverVariableInfo = originalCallInfo.replaceWithVariableAccess() val invokeReceiverVariableInfo = originalCallInfo.replaceWithVariableAccess()
val invokeReceiverVariableWithNoReceiverInfo = invokeReceiverVariableInfo.replaceExplicitReceiver(null)
val towerDataElementsForName = TowerDataElementsForName(invokeReceiverVariableInfo.name, components.towerDataContext) val towerDataElementsForName = TowerDataElementsForName(invokeReceiverVariableInfo.name, components.towerDataContext)
@@ -97,22 +93,36 @@ internal class FirInvokeResolveTowerExtension(
) { ) {
invokeAction(it, invokeReceiverVariableInfo) invokeAction(it, invokeReceiverVariableInfo)
} }
// Try to find "f" property in the given scopes without explicit receiver and then supply "x" as a first argument for invokeExtension
val invokeReceiverVariableWithNoReceiverInfo = invokeReceiverVariableInfo.replaceExplicitReceiver(null)
enqueueInvokeReceiverTask( enqueueInvokeReceiverTask(
originalCallInfo, originalCallInfo,
invokeReceiverVariableWithNoReceiverInfo, invokeReceiverVariableWithNoReceiverInfo,
towerDataElementsForName = towerDataElementsForName, towerDataElementsForName = towerDataElementsForName,
invokeBuiltinExtensionMode = true invokeBuiltinExtensionMode = true
) { ) {
invokeExtensionAction(it, invokeReceiverVariableWithNoReceiverInfo) it.runResolverForNoReceiver(invokeReceiverVariableWithNoReceiverInfo)
} }
} }
/**
* Let we have a call if a form of "x.f()" or "f()"
*
* This method enqueues a task (based on runResolutionForInvokeReceiverVariable) that for each successful property enqueues another task
* that tries to resolve "f()" call itself
*
* @param info describes whole "x.f()" or "f()"
* @param invokeReceiverInfo describes "x.f" or "f" variable (in case of no-receiver call or in case of resolving invokeExtension with "x")
* @param invokeBuiltinExtensionMode is true only when the original call has a form "x.f()" and invokeReceiverInfo is "f"
* @param runResolutionForInvokeReceiverVariable runs the process of looking for the receiver ("x.f" or "f") on the given FirTowerResolveTask
*/
private inline fun enqueueInvokeReceiverTask( private inline fun enqueueInvokeReceiverTask(
info: CallInfo, info: CallInfo,
invokeReceiverInfo: CallInfo, invokeReceiverInfo: CallInfo,
towerDataElementsForName: TowerDataElementsForName = TowerDataElementsForName(invokeReceiverInfo.name, components.towerDataContext), towerDataElementsForName: TowerDataElementsForName = TowerDataElementsForName(invokeReceiverInfo.name, components.towerDataContext),
invokeBuiltinExtensionMode: Boolean, invokeBuiltinExtensionMode: Boolean,
crossinline task: suspend (FirTowerResolveTask) -> Unit crossinline runResolutionForInvokeReceiverVariable: suspend (FirTowerResolveTask) -> Unit
) { ) {
val collector = CandidateCollector(components, components.resolutionStageRunner) val collector = CandidateCollector(components, components.resolutionStageRunner)
val invokeReceiverProcessor = InvokeReceiverResolveTask( val invokeReceiverProcessor = InvokeReceiverResolveTask(
@@ -131,7 +141,7 @@ internal class FirInvokeResolveTowerExtension(
} }
) )
manager.enqueueResolverTask { manager.enqueueResolverTask {
task(invokeReceiverProcessor) runResolutionForInvokeReceiverVariable(invokeReceiverProcessor)
} }
} }
@@ -187,9 +197,12 @@ internal class FirInvokeResolveTowerExtension(
} }
private fun enqueueResolverTasksForInvoke( private fun enqueueResolverTasksForInvoke(
// "x.f.invoke(...)" or "f.invoke(x)" (latter for the invokeExtension calls when "f" has an extension function type)
invokeFunctionInfo: CallInfo, invokeFunctionInfo: CallInfo,
explicitReceiver: ExpressionReceiverValue, explicitReceiver: ExpressionReceiverValue,
// Might be true only if initial call had explicit receiver (x.f()) and here we resolve "f.invoke(x)" with given "f"
invokeBuiltinExtensionMode: Boolean, invokeBuiltinExtensionMode: Boolean,
// The call has a form "f(..)" without explicit receiver and "f" has an extension function type
useImplicitReceiverAsBuiltinInvokeArgument: Boolean, useImplicitReceiverAsBuiltinInvokeArgument: Boolean,
receiverGroup: TowerGroup receiverGroup: TowerGroup
) { ) {
@@ -204,6 +217,7 @@ internal class FirInvokeResolveTowerExtension(
} }
} else { } else {
if (useImplicitReceiverAsBuiltinInvokeArgument) { if (useImplicitReceiverAsBuiltinInvokeArgument) {
require(explicitReceiver.type.fullyExpandedType(context.session).isExtensionFunctionType)
manager.enqueueResolverTask { manager.enqueueResolverTask {
task.runResolverForBuiltinInvokeExtensionWithImplicitArgument( task.runResolverForBuiltinInvokeExtensionWithImplicitArgument(
invokeFunctionInfo, explicitReceiver, invokeFunctionInfo, explicitReceiver,
@@ -221,6 +235,7 @@ internal class FirInvokeResolveTowerExtension(
} }
} }
// For calls having a form of "x.(f)()"
fun enqueueResolveTasksForImplicitInvokeCall(info: CallInfo, receiverExpression: FirExpression) { fun enqueueResolveTasksForImplicitInvokeCall(info: CallInfo, receiverExpression: FirExpression) {
val explicitReceiverValue = ExpressionReceiverValue(receiverExpression) val explicitReceiverValue = ExpressionReceiverValue(receiverExpression)
val task = createInvokeFunctionResolveTask(info, TowerGroup.EmptyRoot) val task = createInvokeFunctionResolveTask(info, TowerGroup.EmptyRoot)
@@ -395,7 +410,9 @@ private class InvokeFunctionResolveTask(
// 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
suspend fun runResolverForBuiltinInvokeExtensionWithImplicitArgument( suspend fun runResolverForBuiltinInvokeExtensionWithImplicitArgument(
// "f.invoke(...)"
info: CallInfo, info: CallInfo,
// "f" should have an extension function type
invokeReceiverValue: ExpressionReceiverValue, invokeReceiverValue: ExpressionReceiverValue,
parentGroupForInvokeCandidates: TowerGroup parentGroupForInvokeCandidates: TowerGroup
) { ) {
@@ -408,6 +425,7 @@ private class InvokeFunctionResolveTask(
processLevel( processLevel(
invokeReceiverValue.toMemberScopeTowerLevel( invokeReceiverValue.toMemberScopeTowerLevel(
// Try to supply `implicitReceiverValue` as an "x" in "f.invoke(x)"
extensionReceiver = implicitReceiverValue, extensionReceiver = implicitReceiverValue,
implicitExtensionInvokeMode = true implicitExtensionInvokeMode = true
), ),