FIR: Simplify and clarify contracts in FirInvokeResolveTowerExtension
This commit is contained in:
+43
-25
@@ -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
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user