FIR resolve: process situation with both implicit receivers properly
This commit is contained in:
@@ -139,9 +139,9 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun ConeCallableSymbol.hasConsistentExtensionReceiver(explicitExtensionReceiver: ExpressionReceiverValue?): Boolean {
|
protected fun ConeCallableSymbol.hasConsistentExtensionReceiver(extensionReceiver: ReceiverValue?): Boolean {
|
||||||
val hasExtensionReceiver = hasExtensionReceiver()
|
val hasExtensionReceiver = hasExtensionReceiver()
|
||||||
return hasExtensionReceiver == (explicitExtensionReceiver != null)
|
return hasExtensionReceiver == (extensionReceiver != null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,10 +149,12 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
|
|||||||
// Here we always have an explicit or implicit dispatch receiver, and can access members of its scope
|
// Here we always have an explicit or implicit dispatch receiver, and can access members of its scope
|
||||||
// (which is separated from currently accessible scope, see below)
|
// (which is separated from currently accessible scope, see below)
|
||||||
// So: dispatch receiver = given explicit or implicit receiver (always present)
|
// So: dispatch receiver = given explicit or implicit receiver (always present)
|
||||||
// So: extension receiver = either none, if dispatch receiver = explicit receiver, or given explicit receiver, otherwise
|
// So: extension receiver = either none, if dispatch receiver = explicit receiver,
|
||||||
|
// or given implicit or explicit receiver, otherwise
|
||||||
class MemberScopeTowerLevel(
|
class MemberScopeTowerLevel(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
val dispatchReceiver: ReceiverValue
|
val dispatchReceiver: ReceiverValue,
|
||||||
|
val implicitExtensionReceiver: ReceiverValue? = null
|
||||||
) : SessionBasedTowerLevel(session) {
|
) : SessionBasedTowerLevel(session) {
|
||||||
|
|
||||||
private fun <T : ConeSymbol> processMembers(
|
private fun <T : ConeSymbol> processMembers(
|
||||||
@@ -160,9 +162,11 @@ class MemberScopeTowerLevel(
|
|||||||
explicitExtensionReceiver: ExpressionReceiverValue?,
|
explicitExtensionReceiver: ExpressionReceiverValue?,
|
||||||
processScopeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction
|
processScopeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction
|
||||||
): ProcessorAction {
|
): ProcessorAction {
|
||||||
|
if (implicitExtensionReceiver != null && explicitExtensionReceiver != null) return ProcessorAction.NEXT
|
||||||
|
val extensionReceiver = implicitExtensionReceiver ?: explicitExtensionReceiver
|
||||||
val scope = dispatchReceiver.type.scope(session, ScopeSession()) ?: return ProcessorAction.NEXT
|
val scope = dispatchReceiver.type.scope(session, ScopeSession()) ?: return ProcessorAction.NEXT
|
||||||
if (scope.processScopeMembers { candidate ->
|
if (scope.processScopeMembers { candidate ->
|
||||||
if (candidate is ConeCallableSymbol && candidate.hasConsistentExtensionReceiver(explicitExtensionReceiver)) {
|
if (candidate is ConeCallableSymbol && candidate.hasConsistentExtensionReceiver(extensionReceiver)) {
|
||||||
// NB: we do not check dispatchReceiverValue != null here,
|
// NB: we do not check dispatchReceiverValue != null here,
|
||||||
// because of objects & constructors (see comments in dispatchReceiverValue() implementation)
|
// because of objects & constructors (see comments in dispatchReceiverValue() implementation)
|
||||||
output.consumeCandidate(candidate, candidate.dispatchReceiverValue())
|
output.consumeCandidate(candidate, candidate.dispatchReceiverValue())
|
||||||
@@ -471,7 +475,18 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
|
|||||||
oldGroup: Int
|
oldGroup: Int
|
||||||
): Int {
|
): Int {
|
||||||
var group = oldGroup
|
var group = oldGroup
|
||||||
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, MemberScopeTowerLevel(session, implicitReceiverValue), collector, group++)
|
towerDataConsumer.consume(
|
||||||
|
TowerDataKind.TOWER_LEVEL,
|
||||||
|
MemberScopeTowerLevel(session, implicitReceiverValue),
|
||||||
|
collector, group++
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is an equivalent to the old "BothTowerLevelAndImplicitReceiver"
|
||||||
|
towerDataConsumer.consume(
|
||||||
|
TowerDataKind.TOWER_LEVEL,
|
||||||
|
MemberScopeTowerLevel(session, implicitReceiverValue, implicitReceiverValue),
|
||||||
|
collector, group++
|
||||||
|
)
|
||||||
|
|
||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user