From e276e8d9f38b74eec08a63e749be7d5eb21e3055 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 1 Oct 2019 13:02:31 +0300 Subject: [PATCH] Don't enter twice local scopes w/out particular name in FIR tower resolver --- .../kotlin/fir/resolve/calls/CallResolver.kt | 37 +++++++++++-------- .../fir/resolve/calls/TowerDataConsumers.kt | 22 ++++++----- .../impl/FirAbstractSimpleImportingScope.kt | 6 +-- .../impl/FirAbstractStarImportingScope.kt | 3 ++ .../kotlin/fir/scopes/impl/FirLocalScope.kt | 4 +- .../jetbrains/kotlin/fir/scopes/FirScope.kt | 6 ++- 6 files changed, 46 insertions(+), 32 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt index a27bfb811e9..3e3b0305ddc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt @@ -7,8 +7,11 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents +import org.jetbrains.kotlin.fir.resolve.calls.TowerDataKind.EMPTY +import org.jetbrains.kotlin.fir.resolve.calls.TowerDataKind.TOWER_LEVEL 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 enum class TowerDataKind { @@ -29,6 +32,7 @@ class CallResolver( private fun processImplicitReceiver( towerDataConsumer: TowerDataConsumer, implicitReceiverValue: ImplicitReceiverValue<*>, + nonEmptyLocalScopes: List, oldGroup: Int ): Int { var group = oldGroup @@ -39,7 +43,7 @@ class CallResolver( // fun test(b: Bar) { b.baz() } // } towerDataConsumer.consume( - TowerDataKind.TOWER_LEVEL, + TOWER_LEVEL, MemberScopeTowerLevel(session, implicitReceiverValue, scopeSession = components.scopeSession), group++ ) @@ -50,7 +54,7 @@ class CallResolver( // fun test() { bar() } // } towerDataConsumer.consume( - TowerDataKind.TOWER_LEVEL, + TOWER_LEVEL, MemberScopeTowerLevel(session, implicitReceiverValue, implicitReceiverValue, components.scopeSession), group++ ) @@ -62,9 +66,9 @@ class CallResolver( // bar() // } // } - for (scope in localScopes) { + for (scope in nonEmptyLocalScopes) { towerDataConsumer.consume( - TowerDataKind.TOWER_LEVEL, + TOWER_LEVEL, ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue), group++ ) @@ -83,7 +87,7 @@ class CallResolver( // } // } towerDataConsumer.consume( - TowerDataKind.TOWER_LEVEL, + TOWER_LEVEL, ScopeTowerLevel(session, components, implicitScope, implicitExtensionReceiver = implicitReceiverValue), group++ ) @@ -97,7 +101,7 @@ class CallResolver( // fun test() { foo() } // } towerDataConsumer.consume( - TowerDataKind.TOWER_LEVEL, + TOWER_LEVEL, ScopeTowerLevel(session, components, implicitCompanionScope, implicitExtensionReceiver = implicitReceiverValue), group++ ) @@ -119,7 +123,7 @@ class CallResolver( // with(a) { with(b) { foo() } } // } towerDataConsumer.consume( - TowerDataKind.TOWER_LEVEL, + TOWER_LEVEL, MemberScopeTowerLevel( session, scopeSession = components.scopeSession, dispatchReceiver = implicitDispatchReceiverValue, @@ -137,7 +141,7 @@ class CallResolver( // } for (scope in topLevelScopes) { towerDataConsumer.consume( - TowerDataKind.TOWER_LEVEL, + TOWER_LEVEL, ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue), group++ ) @@ -147,7 +151,7 @@ class CallResolver( } val collector by lazy { CandidateCollector(components, resolutionStageRunner) } - lateinit var towerDataConsumer: TowerDataConsumer + private lateinit var towerDataConsumer: TowerDataConsumer private lateinit var implicitReceiverValues: List> fun runTowerResolver(consumer: TowerDataConsumer, implicitReceiverValues: List>): CandidateCollector { @@ -158,12 +162,15 @@ class CallResolver( // Member of explicit receiver' type (this stage does nothing without explicit receiver) // class Foo(val x: Int) // fun test(f: Foo) { f.x } - towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++) + towerDataConsumer.consume(EMPTY, TowerScopeLevel.Empty, group++) // Member of local scope // fun test(x: Int) = x + val nonEmptyLocalScopes = mutableListOf() for (scope in localScopes) { - towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++) + if (towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++) != NONE) { + nonEmptyLocalScopes += scope + } } var blockDispatchReceivers = false @@ -172,7 +179,7 @@ class CallResolver( for (implicitReceiverValue in implicitReceiverValues) { if (!blockDispatchReceivers || implicitReceiverValue !is ImplicitDispatchReceiverValue) { // Direct use of implicit receiver (see inside) - group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, group) + group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, nonEmptyLocalScopes, group) } val implicitScope = implicitReceiverValue.implicitScope if (implicitScope != null) { @@ -181,7 +188,7 @@ class CallResolver( // val x = 0 // class Nested { val y = x } // } - towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, components, implicitScope), group++) + towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, implicitScope), group++) } if (implicitReceiverValue is ImplicitDispatchReceiverValue) { val implicitCompanionScope = implicitReceiverValue.implicitCompanionScope @@ -191,7 +198,7 @@ class CallResolver( // companion object { val x = 0 } // class Nested { val y = x } // } - towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, components, implicitCompanionScope), group++) + towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, implicitCompanionScope), group++) } if (!implicitReceiverValue.boundSymbol.fir.isInner) { blockDispatchReceivers = true @@ -203,7 +210,7 @@ class CallResolver( // val x = 0 // fun test() { x } for (scope in topLevelScopes) { - towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++) + towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++) } return collector diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerDataConsumers.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerDataConsumers.kt index 6eb7fed9b37..65584d0bee7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerDataConsumers.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerDataConsumers.kt @@ -92,13 +92,15 @@ class PrioritizedTowerDataConsumer( group: Int ): ProcessorAction { if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT + var empty = true for ((index, consumer) in consumers.withIndex()) { val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index) - if (action.stop()) { - return ProcessorAction.STOP + when (action) { + ProcessorAction.STOP -> return action + ProcessorAction.NEXT -> empty = false } } - return ProcessorAction.NEXT + return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT } } @@ -123,16 +125,18 @@ class AccumulatingTowerDataConsumer( if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT accumulatedTowerData += TowerData(kind, towerScopeLevel, group) - if (initialConsumer.consume(kind, towerScopeLevel, group).stop()) { - return ProcessorAction.STOP + var empty = true + when (val action = initialConsumer.consume(kind, towerScopeLevel, group)) { + ProcessorAction.STOP -> return action + ProcessorAction.NEXT -> empty = false } for (consumer in additionalConsumers) { - val action = consumer.consume(kind, towerScopeLevel, group) - if (action.stop()) { - return ProcessorAction.STOP + when (val action = consumer.consume(kind, towerScopeLevel, group)) { + ProcessorAction.STOP -> return action + ProcessorAction.NEXT -> empty = false } } - return ProcessorAction.NEXT + return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT } fun addConsumer(consumer: TowerDataConsumer): ProcessorAction { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractSimpleImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractSimpleImportingScope.kt index 15f2997a69b..c5830c60019 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractSimpleImportingScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractSimpleImportingScope.kt @@ -50,10 +50,8 @@ abstract class FirAbstractSimpleImportingScope( token: TowerScopeLevel.Token, processor: (FirCallableSymbol<*>) -> ProcessorAction ): ProcessorAction { - - - val imports = simpleImports[name] ?: return ProcessorAction.NEXT - if (imports.isEmpty()) return ProcessorAction.NEXT + val imports = simpleImports[name] ?: return ProcessorAction.NONE + if (imports.isEmpty()) return ProcessorAction.NONE for (import in imports) { if (processCallables(import, import.importedName!!, token, processor).stop()) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractStarImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractStarImportingScope.kt index 39d728dedb5..e98995566d6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractStarImportingScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractStarImportingScope.kt @@ -50,6 +50,9 @@ abstract class FirAbstractStarImportingScope( token: TowerScopeLevel.Token, processor: (FirCallableSymbol<*>) -> ProcessorAction ): ProcessorAction { + if (starImports.isEmpty()) { + return ProcessorAction.NONE + } for (import in starImports) { if (processCallables(import, name, token, processor).stop()) { return ProcessorAction.STOP diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirLocalScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirLocalScope.kt index 747989165f9..a2a8dc9568b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirLocalScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirLocalScope.kt @@ -39,7 +39,7 @@ class FirLocalScope : FirScope() { if (prop != null) { return processor(prop) } - return ProcessorAction.NEXT + return ProcessorAction.NONE } override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction { @@ -47,6 +47,6 @@ class FirLocalScope : FirScope() { if (prop != null) { return processor(prop) } - return ProcessorAction.NEXT + return ProcessorAction.NONE } } \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt index bb5ffedae7f..25fe6ede7d1 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt @@ -54,15 +54,17 @@ enum class FirPosition(val allowTypeParameters: Boolean = true) { enum class ProcessorAction { STOP, - NEXT; + NEXT, + NONE; operator fun not(): Boolean { return when (this) { STOP -> true NEXT -> false + NONE -> false } } fun stop() = this == STOP - fun next() = this == NEXT + fun next() = this != STOP }