diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt index 5208d4440a5..e20cc7c0c37 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt @@ -159,6 +159,7 @@ private class NoExplicitReceiverScopeTowerProcessor( when (data) { is TowerData.TowerLevel -> data.level.recordLookup(name) is TowerData.BothTowerLevelAndImplicitReceiver -> data.level.recordLookup(name) + is TowerData.ForLookupForNoExplicitReceiver -> data.level.recordLookup(name) } } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index d27baec8aac..351bea26c1a 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -62,6 +62,8 @@ sealed class TowerData { class OnlyImplicitReceiver(val implicitReceiver: ReceiverValueWithSmartCastInfo): TowerData() class TowerLevel(val level: ScopeTowerLevel) : TowerData() class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValueWithSmartCastInfo) : TowerData() + // Has the same meaning as BothTowerLevelAndImplicitReceiver, but it's only used for names lookup, so it doesn't need implicit receiver + class ForLookupForNoExplicitReceiver(val level: ScopeTowerLevel) : TowerData() } interface ScopeTowerProcessor { @@ -98,26 +100,44 @@ class TowerResolver { resultCollector: ResultCollector, useOrder: Boolean, name: Name - ): Collection = with(Task()) { - this@run.run(processor, resultCollector, useOrder, name) - } + ): Collection = Task(this, processor, resultCollector, useOrder, name).run() private data class ScopeLevelsAndSkippedForLookups( val levelsToProcess: Collection, val levelsToSkip: Collection ) - private inner class Task { - private fun ImplicitScopeTower.createNonLocalLevels(name: Name): ScopeLevelsAndSkippedForLookups { + private inner class Task( + private val implicitScopeTower: ImplicitScopeTower, + private val processor: ScopeTowerProcessor, + private val resultCollector: ResultCollector, + private val useOrder: Boolean, + private val name: Name + ) { + private val skippedDataForLookup = mutableListOf() + + private val localLevels: Collection by lazy(LazyThreadSafetyMode.NONE) { + implicitScopeTower.lexicalScope.parentsWithSelf. + filterIsInstance().filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }. + map { ScopeBasedTowerLevel(implicitScopeTower, it) }.toList() + } + + private val nonLocalLevels: Collection by lazy(LazyThreadSafetyMode.NONE) { + implicitScopeTower.createNonLocalLevels() + } + + val hidesMembersLevel = HidesMembersTowerLevel(implicitScopeTower) + val syntheticLevel = SyntheticScopeBasedTowerLevel(implicitScopeTower, implicitScopeTower.syntheticScopes) + + private fun ImplicitScopeTower.createNonLocalLevels(): Collection { val mainResult = mutableListOf() - val skippedLevels = mutableListOf() fun addLevel(scopeTowerLevel: ScopeTowerLevel, mayFitForName: Boolean) { if (mayFitForName) { mainResult.add(scopeTowerLevel) } else { - skippedLevels.add(scopeTowerLevel) + skippedDataForLookup.add(TowerData.ForLookupForNoExplicitReceiver(scopeTowerLevel)) } } @@ -145,38 +165,22 @@ class TowerResolver { } } - return ScopeLevelsAndSkippedForLookups(mainResult, skippedLevels) + return mainResult } - fun ImplicitScopeTower.run( - processor: ScopeTowerProcessor, - resultCollector: ResultCollector, - useOrder: Boolean, - name: Name - ): Collection { - val skippedDataForLookup = mutableListOf() + private fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this)?.also { + recordLookups() + } - fun recordLookups() { - processor.recordLookups(skippedDataForLookup, name) + private fun TowerData.process(mayFitForName: Boolean): Collection? { + if (!mayFitForName) { + skippedDataForLookup.add(this) + return null } + return process() + } - fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this)?.also { - recordLookups() - } - - fun TowerData.process(mayFitForName: Boolean): Collection? { - if (!mayFitForName) { - skippedDataForLookup.add(this) - return null - } - return process() - } - - // Lazy calculation - var nonLocalLevels: Collection? = null - val hidesMembersLevel = HidesMembersTowerLevel(this) - val syntheticLevel = SyntheticScopeBasedTowerLevel(this, syntheticScopes) - + fun run(): Collection { if (name in HIDES_MEMBERS_NAME_LIST) { // hides members extensions for explicit receiver TowerData.TowerLevel(hidesMembersLevel).process()?.let { return it } @@ -187,25 +191,20 @@ class TowerResolver { // synthetic property for explicit receiver TowerData.TowerLevel(syntheticLevel).process()?.let { return it } - val localLevels = - lexicalScope.parentsWithSelf. - filterIsInstance().filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }. - map { ScopeBasedTowerLevel(this@run, it) }.toList() - // local non-extensions or extension for explicit receiver for (localLevel in localLevels) { TowerData.TowerLevel(localLevel).process()?.let { return it } } - for (scope in lexicalScope.parentsWithSelf) { + for (scope in implicitScopeTower.lexicalScope.parentsWithSelf) { if (scope is LexicalScope) { // statics if (!scope.kind.withLocalDescriptors) { - TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope)) + TowerData.TowerLevel(ScopeBasedTowerLevel(implicitScopeTower, scope)) .process(scope.mayFitForName(name))?.let { return it } } - val implicitReceiver = getImplicitReceiver(scope) + val implicitReceiver = implicitScopeTower.getImplicitReceiver(scope) if (implicitReceiver != null) { if (name in HIDES_MEMBERS_NAME_LIST) { // hides members extensions @@ -213,7 +212,7 @@ class TowerResolver { } // members of implicit receiver or member extension for explicit receiver - TowerData.TowerLevel(MemberScopeTowerLevel(this, implicitReceiver)) + TowerData.TowerLevel(MemberScopeTowerLevel(implicitScopeTower, implicitReceiver)) .process(implicitReceiver.mayFitForName(name))?.let { return it } // synthetic properties @@ -227,12 +226,6 @@ class TowerResolver { TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver).process()?.let { return it } } - if (nonLocalLevels == null) { - val (toProcess, toSkip) = createNonLocalLevels(name) - nonLocalLevels = toProcess - toSkip.mapTo(skippedDataForLookup) { TowerData.BothTowerLevelAndImplicitReceiver(it, implicitReceiver) } - } - // extension for implicit receiver for (nonLocalLevel in nonLocalLevels) { TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver).process()?.let { return it } @@ -240,7 +233,7 @@ class TowerResolver { } } else { - TowerData.TowerLevel(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)) + TowerData.TowerLevel(ImportingScopeBasedTowerLevel(implicitScopeTower, scope as ImportingScope)) .process(scope.mayFitForName(name))?.let { return it } } } @@ -250,6 +243,10 @@ class TowerResolver { return resultCollector.getFinalCandidates() } + private fun recordLookups() { + processor.recordLookups(skippedDataForLookup, name) + } + private fun ReceiverValueWithSmartCastInfo.mayFitForName(name: Name): Boolean { if (receiverValue.type.mayFitForName(name)) return true if (possibleTypes.isEmpty()) return false