FIR resolve: process situation with both implicit receivers properly

This commit is contained in:
Mikhail Glukhikh
2019-04-26 10:48:40 +03:00
parent 3636046e2d
commit a4b4db5589
@@ -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
} }