Don't enter twice local scopes w/out particular name in FIR tower resolver
This commit is contained in:
@@ -7,8 +7,11 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
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.resolve.transformers.ReturnTypeCalculator
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NONE
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||||
|
|
||||||
enum class TowerDataKind {
|
enum class TowerDataKind {
|
||||||
@@ -29,6 +32,7 @@ class CallResolver(
|
|||||||
private fun processImplicitReceiver(
|
private fun processImplicitReceiver(
|
||||||
towerDataConsumer: TowerDataConsumer,
|
towerDataConsumer: TowerDataConsumer,
|
||||||
implicitReceiverValue: ImplicitReceiverValue<*>,
|
implicitReceiverValue: ImplicitReceiverValue<*>,
|
||||||
|
nonEmptyLocalScopes: List<FirLocalScope>,
|
||||||
oldGroup: Int
|
oldGroup: Int
|
||||||
): Int {
|
): Int {
|
||||||
var group = oldGroup
|
var group = oldGroup
|
||||||
@@ -39,7 +43,7 @@ class CallResolver(
|
|||||||
// fun test(b: Bar) { b.baz() }
|
// fun test(b: Bar) { b.baz() }
|
||||||
// }
|
// }
|
||||||
towerDataConsumer.consume(
|
towerDataConsumer.consume(
|
||||||
TowerDataKind.TOWER_LEVEL,
|
TOWER_LEVEL,
|
||||||
MemberScopeTowerLevel(session, implicitReceiverValue, scopeSession = components.scopeSession),
|
MemberScopeTowerLevel(session, implicitReceiverValue, scopeSession = components.scopeSession),
|
||||||
group++
|
group++
|
||||||
)
|
)
|
||||||
@@ -50,7 +54,7 @@ class CallResolver(
|
|||||||
// fun test() { bar() }
|
// fun test() { bar() }
|
||||||
// }
|
// }
|
||||||
towerDataConsumer.consume(
|
towerDataConsumer.consume(
|
||||||
TowerDataKind.TOWER_LEVEL,
|
TOWER_LEVEL,
|
||||||
MemberScopeTowerLevel(session, implicitReceiverValue, implicitReceiverValue, components.scopeSession),
|
MemberScopeTowerLevel(session, implicitReceiverValue, implicitReceiverValue, components.scopeSession),
|
||||||
group++
|
group++
|
||||||
)
|
)
|
||||||
@@ -62,9 +66,9 @@ class CallResolver(
|
|||||||
// bar()
|
// bar()
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
for (scope in localScopes) {
|
for (scope in nonEmptyLocalScopes) {
|
||||||
towerDataConsumer.consume(
|
towerDataConsumer.consume(
|
||||||
TowerDataKind.TOWER_LEVEL,
|
TOWER_LEVEL,
|
||||||
ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue),
|
ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue),
|
||||||
group++
|
group++
|
||||||
)
|
)
|
||||||
@@ -83,7 +87,7 @@ class CallResolver(
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
towerDataConsumer.consume(
|
towerDataConsumer.consume(
|
||||||
TowerDataKind.TOWER_LEVEL,
|
TOWER_LEVEL,
|
||||||
ScopeTowerLevel(session, components, implicitScope, implicitExtensionReceiver = implicitReceiverValue),
|
ScopeTowerLevel(session, components, implicitScope, implicitExtensionReceiver = implicitReceiverValue),
|
||||||
group++
|
group++
|
||||||
)
|
)
|
||||||
@@ -97,7 +101,7 @@ class CallResolver(
|
|||||||
// fun test() { foo() }
|
// fun test() { foo() }
|
||||||
// }
|
// }
|
||||||
towerDataConsumer.consume(
|
towerDataConsumer.consume(
|
||||||
TowerDataKind.TOWER_LEVEL,
|
TOWER_LEVEL,
|
||||||
ScopeTowerLevel(session, components, implicitCompanionScope, implicitExtensionReceiver = implicitReceiverValue),
|
ScopeTowerLevel(session, components, implicitCompanionScope, implicitExtensionReceiver = implicitReceiverValue),
|
||||||
group++
|
group++
|
||||||
)
|
)
|
||||||
@@ -119,7 +123,7 @@ class CallResolver(
|
|||||||
// with(a) { with(b) { foo() } }
|
// with(a) { with(b) { foo() } }
|
||||||
// }
|
// }
|
||||||
towerDataConsumer.consume(
|
towerDataConsumer.consume(
|
||||||
TowerDataKind.TOWER_LEVEL,
|
TOWER_LEVEL,
|
||||||
MemberScopeTowerLevel(
|
MemberScopeTowerLevel(
|
||||||
session, scopeSession = components.scopeSession,
|
session, scopeSession = components.scopeSession,
|
||||||
dispatchReceiver = implicitDispatchReceiverValue,
|
dispatchReceiver = implicitDispatchReceiverValue,
|
||||||
@@ -137,7 +141,7 @@ class CallResolver(
|
|||||||
// }
|
// }
|
||||||
for (scope in topLevelScopes) {
|
for (scope in topLevelScopes) {
|
||||||
towerDataConsumer.consume(
|
towerDataConsumer.consume(
|
||||||
TowerDataKind.TOWER_LEVEL,
|
TOWER_LEVEL,
|
||||||
ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue),
|
ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue),
|
||||||
group++
|
group++
|
||||||
)
|
)
|
||||||
@@ -147,7 +151,7 @@ class CallResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val collector by lazy { CandidateCollector(components, resolutionStageRunner) }
|
val collector by lazy { CandidateCollector(components, resolutionStageRunner) }
|
||||||
lateinit var towerDataConsumer: TowerDataConsumer
|
private lateinit var towerDataConsumer: TowerDataConsumer
|
||||||
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue<*>>
|
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue<*>>
|
||||||
|
|
||||||
fun runTowerResolver(consumer: TowerDataConsumer, implicitReceiverValues: List<ImplicitReceiverValue<*>>): CandidateCollector {
|
fun runTowerResolver(consumer: TowerDataConsumer, implicitReceiverValues: List<ImplicitReceiverValue<*>>): CandidateCollector {
|
||||||
@@ -158,12 +162,15 @@ class CallResolver(
|
|||||||
// Member of explicit receiver' type (this stage does nothing without explicit receiver)
|
// Member of explicit receiver' type (this stage does nothing without explicit receiver)
|
||||||
// class Foo(val x: Int)
|
// class Foo(val x: Int)
|
||||||
// fun test(f: Foo) { f.x }
|
// fun test(f: Foo) { f.x }
|
||||||
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++)
|
towerDataConsumer.consume(EMPTY, TowerScopeLevel.Empty, group++)
|
||||||
|
|
||||||
// Member of local scope
|
// Member of local scope
|
||||||
// fun test(x: Int) = x
|
// fun test(x: Int) = x
|
||||||
|
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
|
||||||
for (scope in localScopes) {
|
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
|
var blockDispatchReceivers = false
|
||||||
@@ -172,7 +179,7 @@ class CallResolver(
|
|||||||
for (implicitReceiverValue in implicitReceiverValues) {
|
for (implicitReceiverValue in implicitReceiverValues) {
|
||||||
if (!blockDispatchReceivers || implicitReceiverValue !is ImplicitDispatchReceiverValue) {
|
if (!blockDispatchReceivers || implicitReceiverValue !is ImplicitDispatchReceiverValue) {
|
||||||
// Direct use of implicit receiver (see inside)
|
// Direct use of implicit receiver (see inside)
|
||||||
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, group)
|
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, nonEmptyLocalScopes, group)
|
||||||
}
|
}
|
||||||
val implicitScope = implicitReceiverValue.implicitScope
|
val implicitScope = implicitReceiverValue.implicitScope
|
||||||
if (implicitScope != null) {
|
if (implicitScope != null) {
|
||||||
@@ -181,7 +188,7 @@ class CallResolver(
|
|||||||
// val x = 0
|
// val x = 0
|
||||||
// class Nested { val y = x }
|
// 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) {
|
if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
|
||||||
val implicitCompanionScope = implicitReceiverValue.implicitCompanionScope
|
val implicitCompanionScope = implicitReceiverValue.implicitCompanionScope
|
||||||
@@ -191,7 +198,7 @@ class CallResolver(
|
|||||||
// companion object { val x = 0 }
|
// companion object { val x = 0 }
|
||||||
// class Nested { val y = x }
|
// 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) {
|
if (!implicitReceiverValue.boundSymbol.fir.isInner) {
|
||||||
blockDispatchReceivers = true
|
blockDispatchReceivers = true
|
||||||
@@ -203,7 +210,7 @@ class CallResolver(
|
|||||||
// val x = 0
|
// val x = 0
|
||||||
// fun test() { x }
|
// fun test() { x }
|
||||||
for (scope in topLevelScopes) {
|
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
|
return collector
|
||||||
|
|||||||
+13
-9
@@ -92,13 +92,15 @@ class PrioritizedTowerDataConsumer(
|
|||||||
group: Int
|
group: Int
|
||||||
): ProcessorAction {
|
): ProcessorAction {
|
||||||
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||||
|
var empty = true
|
||||||
for ((index, consumer) in consumers.withIndex()) {
|
for ((index, consumer) in consumers.withIndex()) {
|
||||||
val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index)
|
val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index)
|
||||||
if (action.stop()) {
|
when (action) {
|
||||||
return ProcessorAction.STOP
|
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
|
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
|
||||||
accumulatedTowerData += TowerData(kind, towerScopeLevel, group)
|
accumulatedTowerData += TowerData(kind, towerScopeLevel, group)
|
||||||
|
|
||||||
if (initialConsumer.consume(kind, towerScopeLevel, group).stop()) {
|
var empty = true
|
||||||
return ProcessorAction.STOP
|
when (val action = initialConsumer.consume(kind, towerScopeLevel, group)) {
|
||||||
|
ProcessorAction.STOP -> return action
|
||||||
|
ProcessorAction.NEXT -> empty = false
|
||||||
}
|
}
|
||||||
for (consumer in additionalConsumers) {
|
for (consumer in additionalConsumers) {
|
||||||
val action = consumer.consume(kind, towerScopeLevel, group)
|
when (val action = consumer.consume(kind, towerScopeLevel, group)) {
|
||||||
if (action.stop()) {
|
ProcessorAction.STOP -> return action
|
||||||
return ProcessorAction.STOP
|
ProcessorAction.NEXT -> empty = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ProcessorAction.NEXT
|
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addConsumer(consumer: TowerDataConsumer): ProcessorAction {
|
fun addConsumer(consumer: TowerDataConsumer): ProcessorAction {
|
||||||
|
|||||||
+2
-4
@@ -50,10 +50,8 @@ abstract class FirAbstractSimpleImportingScope(
|
|||||||
token: TowerScopeLevel.Token<T>,
|
token: TowerScopeLevel.Token<T>,
|
||||||
processor: (FirCallableSymbol<*>) -> ProcessorAction
|
processor: (FirCallableSymbol<*>) -> ProcessorAction
|
||||||
): ProcessorAction {
|
): ProcessorAction {
|
||||||
|
val imports = simpleImports[name] ?: return ProcessorAction.NONE
|
||||||
|
if (imports.isEmpty()) return ProcessorAction.NONE
|
||||||
val imports = simpleImports[name] ?: return ProcessorAction.NEXT
|
|
||||||
if (imports.isEmpty()) return ProcessorAction.NEXT
|
|
||||||
|
|
||||||
for (import in imports) {
|
for (import in imports) {
|
||||||
if (processCallables(import, import.importedName!!, token, processor).stop()) {
|
if (processCallables(import, import.importedName!!, token, processor).stop()) {
|
||||||
|
|||||||
+3
@@ -50,6 +50,9 @@ abstract class FirAbstractStarImportingScope(
|
|||||||
token: TowerScopeLevel.Token<T>,
|
token: TowerScopeLevel.Token<T>,
|
||||||
processor: (FirCallableSymbol<*>) -> ProcessorAction
|
processor: (FirCallableSymbol<*>) -> ProcessorAction
|
||||||
): ProcessorAction {
|
): ProcessorAction {
|
||||||
|
if (starImports.isEmpty()) {
|
||||||
|
return ProcessorAction.NONE
|
||||||
|
}
|
||||||
for (import in starImports) {
|
for (import in starImports) {
|
||||||
if (processCallables(import, name, token, processor).stop()) {
|
if (processCallables(import, name, token, processor).stop()) {
|
||||||
return ProcessorAction.STOP
|
return ProcessorAction.STOP
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class FirLocalScope : FirScope() {
|
|||||||
if (prop != null) {
|
if (prop != null) {
|
||||||
return processor(prop)
|
return processor(prop)
|
||||||
}
|
}
|
||||||
return ProcessorAction.NEXT
|
return ProcessorAction.NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||||
@@ -47,6 +47,6 @@ class FirLocalScope : FirScope() {
|
|||||||
if (prop != null) {
|
if (prop != null) {
|
||||||
return processor(prop)
|
return processor(prop)
|
||||||
}
|
}
|
||||||
return ProcessorAction.NEXT
|
return ProcessorAction.NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,15 +54,17 @@ enum class FirPosition(val allowTypeParameters: Boolean = true) {
|
|||||||
|
|
||||||
enum class ProcessorAction {
|
enum class ProcessorAction {
|
||||||
STOP,
|
STOP,
|
||||||
NEXT;
|
NEXT,
|
||||||
|
NONE;
|
||||||
|
|
||||||
operator fun not(): Boolean {
|
operator fun not(): Boolean {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
STOP -> true
|
STOP -> true
|
||||||
NEXT -> false
|
NEXT -> false
|
||||||
|
NONE -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stop() = this == STOP
|
fun stop() = this == STOP
|
||||||
fun next() = this == NEXT
|
fun next() = this != STOP
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user