diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/companionVsSuperStatic.kt b/compiler/fir/analysis-tests/testData/resolve/callResolution/companionVsSuperStatic.kt new file mode 100644 index 0000000000000000000000000000000000000000..c134d8a4273c95af9620e38545bd6d87ee89b44f --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/companionVsSuperStatic.kt @@ -0,0 +1,17 @@ +// FILE: JavaClass.java + +public class JavaClass { + public static String FIELD = ""; +} + +// FILE: main.kt + +class A : JavaClass() { + companion object { + val FIELD = 1 + } + + fun foo() { + FIELD + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/companionVsSuperStatic.txt b/compiler/fir/analysis-tests/testData/resolve/callResolution/companionVsSuperStatic.txt new file mode 100644 index 0000000000000000000000000000000000000000..72a5fa32232739501aad1d0e06394485210e0508 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/companionVsSuperStatic.txt @@ -0,0 +1,21 @@ +FILE: main.kt + public final class A : R|JavaClass| { + public constructor(): R|A| { + super() + } + + public final companion object Companion : R|kotlin/Any| { + private constructor(): R|A.Companion| { + super() + } + + public final val FIELD: R|kotlin/Int| = Int(1) + public get(): R|kotlin/Int| + + } + + public final fun foo(): R|kotlin/Unit| { + this@R|/A.Companion|.R|/A.Companion.FIELD| + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/objectInnerClass.txt b/compiler/fir/analysis-tests/testData/resolve/objectInnerClass.txt index 1a136fe2e1c4ed826325291768f444c95c4ad82c..960ad741b7b3e82298e148e9b6b5618bb9ea4b4f 100644 --- a/compiler/fir/analysis-tests/testData/resolve/objectInnerClass.txt +++ b/compiler/fir/analysis-tests/testData/resolve/objectInnerClass.txt @@ -169,14 +169,14 @@ FILE: objectInnerClass.kt } public[local] final fun caseForBase(): R|kotlin/Unit| { - lval base: R|Case3..Base| = R|/Case3..Base.Base|(R|/B.B|()) + lval base: R|Case3..Base| = this@R|/anonymous|.R|/Case3..Base.Base|(R|/B.B|()) R|/base|.R|/Case3..Base.baseFun|() R|/base|.R|/Case3..Base.property| (this@R|/anonymous|, R|/base|).R|/anonymous.hoo|() } public[local] final fun caseForChild(): R|kotlin/Unit| { - lval child: R|Case3..Child| = R|/Case3..Child.Child|(R|/B.B|()) + lval child: R|Case3..Child| = this@R|/anonymous|.R|/Case3..Child.Child|(R|/B.B|()) R|/child|.R|/Case3..Base.baseFun|() R|/child|.R|/Case3..Base.property| R|/child|.R|/Case3..Child.foo|() diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index b293dc814619ce80ea6ec0d8469ab8b002f7fc23..13484d42b52ecf82134813213563bffb3b6a5c9f 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -589,6 +589,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/companionInvoke.kt"); } + @TestMetadata("companionVsSuperStatic.kt") + public void testCompanionVsSuperStatic() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/companionVsSuperStatic.kt"); + } + @TestMetadata("debugExpressionType.kt") public void testDebugExpressionType() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/debugExpressionType.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 720f12bbaf3d6f52b147c32f64788470e4ae66d9..f0cf45eb59d57d01b3cd7edb300515babdededeb 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -589,6 +589,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/companionInvoke.kt"); } + @TestMetadata("companionVsSuperStatic.kt") + public void testCompanionVsSuperStatic() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/companionVsSuperStatic.kt"); + } + @TestMetadata("debugExpressionType.kt") public void testDebugExpressionType() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/debugExpressionType.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt index 8bf672c58792e81dfbadbff4c0f2913e001cc4d2..ceaa22bd6615ccdacdccc205284dafe4fa9f0f98 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.resolve import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf import org.jetbrains.kotlin.fir.FirCallResolver import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSymbolOwner @@ -19,9 +20,10 @@ import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol -import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addIfNotNull interface SessionHolder { val session: FirSession @@ -33,9 +35,9 @@ interface BodyResolveComponents : SessionHolder { val implicitReceiverStack: ImplicitReceiverStack val containingDeclarations: List val fileImportsScope: List - val typeParametersScopes: List + val towerDataElements: List val localScopes: FirLocalScopes - val localContextForAnonymousFunctions: LocalContextForAnonymousFunctions + val towerDataContextForAnonymousFunctions: TowerDataContextForAnonymousFunctions val noExpectedType: FirTypeRef val symbolProvider: FirSymbolProvider val file: FirFile @@ -56,14 +58,86 @@ interface BodyResolveComponents : SessionHolder { } typealias FirLocalScopes = PersistentList -typealias FirTypeParametersScopes = PersistentList -class FirLocalContext( - val localScopes: FirLocalScopes, - val implicitReceiverStack: MutableImplicitReceiverStack -) +class FirTowerDataContext private constructor( + val towerDataElements: PersistentList, + // These properties are effectively redundant, their content should be consistent with `towerDataElements`, + // i.e. implicitReceiverStack == towerDataElements.mapNotNull { it.receiver } + // i.e. localScopes == towerDataElements.mapNotNull { it.scope?.takeIf { it.isLocal } } + val implicitReceiverStack: PersistentImplicitReceiverStack, + val localScopes: FirLocalScopes +) { + + constructor() : this( + persistentListOf(), + PersistentImplicitReceiverStack(), + persistentListOf() + ) + + fun setLastLocalScope(newLastScope: FirLocalScope): FirTowerDataContext { + val oldLastScope = localScopes.last() + val indexOfLastLocalScope = towerDataElements.indexOfLast { it.scope === oldLastScope } + + return FirTowerDataContext( + towerDataElements.set(indexOfLastLocalScope, newLastScope.asTowerDataElement(isLocal = true)), + implicitReceiverStack, + localScopes.set(localScopes.lastIndex, newLastScope) + ) + } + + fun addTowerDataElements(newElements: List): FirTowerDataContext { + return FirTowerDataContext( + towerDataElements.addAll(newElements), + implicitReceiverStack.addAll(newElements.mapNotNull { it.implicitReceiver }), + localScopes + ) + } + + fun addLocalScope(localScope: FirLocalScope): FirTowerDataContext { + return FirTowerDataContext( + towerDataElements.add(localScope.asTowerDataElement(isLocal = true)), + implicitReceiverStack, + localScopes.add(localScope) + ) + } + + fun addReceiver(name: Name?, implicitReceiverValue: ImplicitReceiverValue<*>): FirTowerDataContext { + return FirTowerDataContext( + towerDataElements.add(implicitReceiverValue.asTowerDataElement()), + implicitReceiverStack.add(name, implicitReceiverValue), + localScopes + ) + } + + fun addNonLocalScopeIfNotNull(scope: FirScope?): FirTowerDataContext { + if (scope == null) return this + return addNonLocalScope(scope) + } + + private fun addNonLocalScope(scope: FirScope): FirTowerDataContext { + return FirTowerDataContext( + towerDataElements.add(scope.asTowerDataElement(isLocal = false)), + implicitReceiverStack, + localScopes + ) + } +} + +class FirTowerDataElement(val scope: FirScope?, val implicitReceiver: ImplicitReceiverValue<*>?, val isLocal: Boolean) + +fun ImplicitReceiverValue<*>.asTowerDataElement(): FirTowerDataElement = + FirTowerDataElement(scope = null, this, isLocal = false) + +fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement = + FirTowerDataElement(this, implicitReceiver = null, isLocal) -typealias LocalContextForAnonymousFunctions = Map +typealias TowerDataContextForAnonymousFunctions = Map + +class FirTowerDataContextsForClassParts( + val forNestedClasses: FirTowerDataContext, + val forConstructorHeaders: FirTowerDataContext, + val primaryConstructorParametersScope: FirLocalScope?, +) // --------------------------------------- Utils --------------------------------------- @@ -81,22 +155,10 @@ fun SessionHolder.collectImplicitReceivers( val implicitCompanionValues = mutableListOf>() val implicitReceiverValue = when (owner) { is FirClass<*> -> { - // Questionable: performance - (owner as? FirRegularClass)?.companionObject?.let { companion -> - implicitCompanionValues += ImplicitDispatchReceiverValue( - companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION - ) - } - lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull { - val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass - superClass?.companionObject?.let { companion -> - implicitCompanionValues += ImplicitDispatchReceiverValue( - companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE - ) - } - } - // --- - ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession) + val towerElementsForClass = collectTowerDataElementsForClass(owner, type) + implicitCompanionValues.addAll(towerElementsForClass.implicitCompanionValues) + + towerElementsForClass.thisReceiver } is FirFunction<*> -> { ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) @@ -110,3 +172,54 @@ fun SessionHolder.collectImplicitReceivers( } return ImplicitReceivers(implicitReceiverValue, implicitCompanionValues.asReversed()) } + +fun SessionHolder.collectTowerDataElementsForClass(owner: FirClass<*>, defaultType: ConeKotlinType): TowerElementsForClass { + val allImplicitCompanionValues = mutableListOf>() + + val companionObject = (owner as? FirRegularClass)?.companionObject + val companionReceiver = companionObject?.let { companion -> + ImplicitDispatchReceiverValue( + companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION + ) + } + allImplicitCompanionValues.addIfNotNull(companionReceiver) + + val superClassesStaticsAndCompanionReceivers = mutableListOf() + for (superType in lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session)) { + val superClass = superType.fullyExpandedType(session).lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: continue + + superClass.staticScope(this)?.asTowerDataElement(isLocal = false)?.let(superClassesStaticsAndCompanionReceivers::add) + + (superClass as? FirRegularClass)?.companionObject?.let { companion -> + val superCompanionReceiver = ImplicitDispatchReceiverValue( + companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE + ) + + superClassesStaticsAndCompanionReceivers += superCompanionReceiver.asTowerDataElement() + allImplicitCompanionValues += superCompanionReceiver + } + } + + val thisReceiver = ImplicitDispatchReceiverValue(owner.symbol, defaultType, session, scopeSession) + + return TowerElementsForClass( + thisReceiver, + owner.staticScope(this), + companionReceiver, + companionObject?.staticScope(this), + superClassesStaticsAndCompanionReceivers, + allImplicitCompanionValues + ) +} + +private fun FirClass<*>.staticScope(sessionHolder: SessionHolder) = + scopeProvider.getStaticScope(this, sessionHolder.session, sessionHolder.scopeSession) + +class TowerElementsForClass( + val thisReceiver: ImplicitReceiverValue<*>, + val staticScope: FirScope?, + val companionReceiver: ImplicitReceiverValue<*>?, + val companionStaticScope: FirScope?, + val superClassesStaticsAndCompanionReceivers: List, + val implicitCompanionValues: List> +) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt index 0020e8951f8c8db5b93c9630315cc6017f6c030c..5ccc3e2c30857e7736bffa9c997bd6403775a80d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt @@ -31,6 +31,10 @@ class PersistentImplicitReceiverStack private constructor( persistentListOf(), ) + fun addAll(receivers: List>): PersistentImplicitReceiverStack { + return receivers.fold(this) { acc, value -> acc.add(name = null, value) } + } + fun add(name: Name?, value: ImplicitReceiverValue<*>): PersistentImplicitReceiverStack { val stack = stack.add(value) val originalTypes = originalTypes.add(value.type) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolverSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolverSession.kt index 152b4beb206bf7a1010360c1ecf4535a2c14fe2f..167ea5509f1b89f45f9fed437249801d990c795a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolverSession.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolverSession.kt @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower -import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.isCompanion import org.jetbrains.kotlin.fir.declarations.isInner import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression @@ -24,7 +21,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope -import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol @@ -42,28 +38,24 @@ class FirTowerResolverSession internal constructor( ) { private data class ImplicitReceiver( val receiver: ImplicitReceiverValue<*>, - val depth: Int, - val usableAsValue: Boolean + val depth: Int ) private val session: FirSession get() = components.session - private val implicitReceivers: List - private val implicitReceiversUsableAsValues: List + private val reversedTowerDataElements = components.towerDataElements.asReversed() - init { - val (implicitReceivers, implicitReceiversUsableAsValues) = prepareImplicitReceivers(components.implicitReceiverStack.receiversAsReversed()) - this.implicitReceivers = implicitReceivers - this.implicitReceiversUsableAsValues = implicitReceiversUsableAsValues + private val localScopes: List = reversedTowerDataElements.mapNotNull { lexical -> + lexical.scope?.takeIf { lexical.isLocal } } - private val localScopes: List = components.localScopes.asReversed() + private val nonLocalLexical = reversedTowerDataElements.filter { !it.isLocal } - private val topLevelScopes: List = - if (components.typeParametersScopes.isEmpty()) - components.fileImportsScope.asReversed() - else - components.typeParametersScopes.asReversed() + components.fileImportsScope.asReversed() + private val implicitReceivers: List by lazy(LazyThreadSafetyMode.NONE) { + reversedTowerDataElements.withIndex().mapNotNull { (index, element) -> + element.implicitReceiver?.let { ImplicitReceiver(it, index) } + } + } fun runResolutionForDelegatingConstructor(info: CallInfo, constructorClassSymbol: FirClassSymbol<*>) { manager.enqueueResolverTask { runResolverForDelegatingConstructorCall(info, constructorClassSymbol) } @@ -209,7 +201,7 @@ class FirTowerResolverSession internal constructor( val scope = constructorClassSymbol.fir.unsubstitutedScope(session, components.scopeSession) if (constructorClassSymbol is FirRegularClassSymbol && constructorClassSymbol.fir.isInner) { // Search for inner constructors only - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues.drop(1)) { + for ((implicitReceiverValue, depth) in implicitReceivers.drop(1)) { processLevel( implicitReceiverValue.toMemberScopeTowerLevel(), info.copy(name = constructorClassSymbol.fir.name), TowerGroup.Implicit(depth) @@ -229,12 +221,39 @@ class FirTowerResolverSession internal constructor( ) { processExtensionsThatHideMembers(info, explicitReceiverValue = null) val nonEmptyLocalScopes = mutableListOf() - processLocalScopesWithNoReceiver(info, nonEmptyLocalScopes) val emptyTopLevelScopes = mutableSetOf() - processImplicitReceiversWithNoExplicit(info, nonEmptyLocalScopes, emptyTopLevelScopes) + val implicitReceiverValuesWithEmptyScopes = mutableSetOf>() + + enumerateTowerLevels( + onLocalScope = { index, scope -> + val result = processLevel( + scope.toScopeTowerLevel(), info, TowerGroup.Local(index) + ) + if (result != ProcessorAction.NONE) { + nonEmptyLocalScopes += scope + } + }, + onNonLocalScope = l@{ index, scope -> + // NB: this check does not work for variables + // because we do not search for objects if we have extension receiver + if (info.callKind != CallKind.VariableAccess && scope in emptyTopLevelScopes) return@l - processTopLevelScopesNoReceiver(info, emptyTopLevelScopes) + processLevel( + scope.toScopeTowerLevel(), info, TowerGroup.NonLocal(index) + ) + }, + onImplicitReceiver = { index, receiver -> + processCandidatesWithGivenImplicitReceiverAsValue( + receiver, + info, + TowerGroup.Implicit(index), + implicitReceiverValuesWithEmptyScopes, + nonEmptyLocalScopes, + emptyTopLevelScopes + ) + } + ) } private suspend fun processExtensionsThatHideMembers( @@ -246,14 +265,15 @@ class FirTowerResolverSession internal constructor( if (!shouldProcessExtensionsBeforeMembers) return - for ((index, topLevelScope) in topLevelScopes.withIndex()) { + val importingScopes = components.fileImportsScope.asReversed() + for ((index, topLevelScope) in importingScopes.withIndex()) { if (explicitReceiverValue != null) { processHideMembersLevel( explicitReceiverValue, topLevelScope, info, index, depth = null, ExplicitReceiverKind.EXTENSION_RECEIVER ) } else { - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { + for ((implicitReceiverValue, depth) in implicitReceivers) { processHideMembersLevel( implicitReceiverValue, topLevelScope, info, index, depth, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER @@ -279,53 +299,6 @@ class FirTowerResolverSession internal constructor( explicitReceiverKind, ) - private suspend fun processLocalScopesWithNoReceiver( - info: CallInfo, - nonEmptyLocalScopes: MutableList - ) { - for ((index, localScope) in localScopes.withIndex()) { - val result = processLevel( - localScope.toScopeTowerLevel(), info, TowerGroup.Local(index) - ) - if (result != ProcessorAction.NONE) { - nonEmptyLocalScopes += localScope - } - } - } - - private suspend fun processImplicitReceiversWithNoExplicit( - info: CallInfo, - nonEmptyLocalScopes: MutableList, - emptyTopLevelScopes: MutableSet - ) { - val implicitReceiverValuesWithEmptyScopes = mutableSetOf>() - for ((implicitReceiverValue, depth, usableAsValue) in implicitReceivers) { - // NB: companions are processed via implicitReceiverValues! - val parentGroup = TowerGroup.Implicit(depth) - - if (usableAsValue) { - processCandidatesWithGivenImplicitReceiverAsValue( - implicitReceiverValue, - info, - parentGroup, - implicitReceiverValuesWithEmptyScopes, - nonEmptyLocalScopes, - emptyTopLevelScopes - ) - } - - if (implicitReceiverValue is ImplicitDispatchReceiverValue) { - val scope = implicitReceiverValue.scope(session, components.scopeSession) - if (scope != null) { - processLevel( - FirStaticScope(scope).toScopeTowerLevel(), - info, parentGroup.Static(depth) - ) - } - } - } - } - private suspend fun processCandidatesWithGivenImplicitReceiverAsValue( receiver: ImplicitReceiverValue<*>, info: CallInfo, @@ -342,45 +315,35 @@ class FirTowerResolverSession internal constructor( implicitReceiverValuesWithEmptyScopes += receiver } - for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) { - processLevel( - localScope.toScopeTowerLevel(extensionReceiver = receiver), - info, parentGroup.Local(localIndex) - ) - } + enumerateTowerLevels( + localScopesToUse = nonEmptyLocalScopes, + onLocalScope = { index, scope -> + processLevel( + scope.toScopeTowerLevel(extensionReceiver = receiver), + info, parentGroup.Local(index) + ) + }, + onNonLocalScope = l@{ index, scope -> + if (scope in emptyTopLevelScopes) return@l - for ((implicitDispatchReceiverValue, dispatchDepth) in implicitReceiversUsableAsValues) { - if (implicitDispatchReceiverValue in implicitReceiverValuesWithEmptyScopes) continue - processLevel( - implicitDispatchReceiverValue.toMemberScopeTowerLevel(extensionReceiver = receiver), - info, parentGroup.Implicit(dispatchDepth) - ) - } + val result = processLevel( + scope.toScopeTowerLevel(extensionReceiver = receiver), + info, parentGroup.NonLocal(index) + ) - for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) { - if (topLevelScope in emptyTopLevelScopes) continue - val result = processLevel( - topLevelScope.toScopeTowerLevel(extensionReceiver = receiver), - info, parentGroup.Top(topIndex) - ) - if (result == ProcessorAction.NONE) { - emptyTopLevelScopes += topLevelScope + if (result == ProcessorAction.NONE) { + emptyTopLevelScopes += scope + } + }, + onImplicitReceiver = l@{ index, implicitReceiverValue -> + if (implicitReceiverValue in implicitReceiverValuesWithEmptyScopes) return@l + processLevel( + implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = receiver), + info, parentGroup.Implicit(index) + ) } - } - } + ) - private suspend fun processTopLevelScopesNoReceiver( - info: CallInfo, - emptyTopLevelScopes: Collection - ) { - for ((index, topLevelScope) in topLevelScopes.withIndex()) { - // NB: this check does not work for variables - // because we do not search for objects if we have extension receiver - if (info.callKind != CallKind.VariableAccess && topLevelScope in emptyTopLevelScopes) continue - processLevel( - topLevelScope.toScopeTowerLevel(), info, TowerGroup.Top(index) - ) - } } private suspend fun runResolverForExpressionReceiver( @@ -404,29 +367,51 @@ class FirTowerResolverSession internal constructor( } val nonEmptyLocalScopes = mutableListOf() - for ((index, localScope) in localScopes.withIndex()) { - if (processScopeForExplicitReceiver( - localScope, + + enumerateTowerLevels( + onLocalScope = { index, scope -> + if (processScopeForExplicitReceiver( + scope, + explicitReceiverValue, + info, + TowerGroup.Local(index) + ) != ProcessorAction.NONE + ) { + nonEmptyLocalScopes += scope + } + }, + onNonLocalScope = { index, scope -> + processScopeForExplicitReceiver( + scope, explicitReceiverValue, info, - TowerGroup.Local(index) - ) != ProcessorAction.NONE - ) { - nonEmptyLocalScopes += localScope + TowerGroup.NonLocal(index) + ) + }, + onImplicitReceiver = { index, implicitReceiverValue -> + processCombinationOfReceivers(implicitReceiverValue, explicitReceiverValue, info, index, nonEmptyLocalScopes) } - } + ) + } - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { - processCombinationOfReceivers(implicitReceiverValue, explicitReceiverValue, info, depth, nonEmptyLocalScopes) + private inline fun enumerateTowerLevels( + onLocalScope: (Int, FirScope) -> Unit, + onNonLocalScope: (Int, FirScope) -> Unit, + onImplicitReceiver: (Int, ImplicitReceiverValue<*>) -> Unit, + localScopesToUse: List = localScopes + ) { + for ((index, localScope) in localScopesToUse.withIndex()) { + onLocalScope(index, localScope) } - for ((index, topLevelScope) in topLevelScopes.withIndex()) { - processScopeForExplicitReceiver( - topLevelScope, - explicitReceiverValue, - info, - TowerGroup.Top(index) - ) + for ((depth, lexical) in nonLocalLexical.withIndex()) { + if (!lexical.isLocal && lexical.scope != null) { + onNonLocalScope(depth, lexical.scope) + } + + lexical.implicitReceiver?.let { implicitReceiverValue -> + onImplicitReceiver(depth, implicitReceiverValue) + } } } @@ -468,26 +453,27 @@ class FirTowerResolverSession internal constructor( implicitReceiverValue.toMemberScopeTowerLevel(), info, parentGroup.Member ) - for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) { - processLevelForPropertyWithInvoke( - localScope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue), - info, parentGroup.Local(localIndex) - ) - } - - for ((implicitDispatchReceiverValue, dispatchDepth) in implicitReceiversUsableAsValues) { - processLevelForPropertyWithInvoke( - implicitDispatchReceiverValue.toMemberScopeTowerLevel(extensionReceiver = implicitReceiverValue), - info, parentGroup.Implicit(dispatchDepth) - ) - } - - for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) { - processLevelForPropertyWithInvoke( - topLevelScope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue), - info, parentGroup.Top(topIndex) - ) - } + enumerateTowerLevels( + localScopesToUse = nonEmptyLocalScopes, + onLocalScope = { index, scope -> + processLevelForPropertyWithInvoke( + scope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue), + info, parentGroup.Local(index) + ) + }, + onNonLocalScope = { index, scope -> + processLevelForPropertyWithInvoke( + scope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue), + info, parentGroup.NonLocal(index) + ) + }, + onImplicitReceiver = { index, receiver -> + processLevelForPropertyWithInvoke( + receiver.toMemberScopeTowerLevel(extensionReceiver = implicitReceiverValue), + info, parentGroup.Implicit(index) + ) + } + ) } private suspend fun runResolverForSuperReceiver( @@ -520,34 +506,34 @@ class FirTowerResolverSession internal constructor( invokeOnGivenReceiverCandidateFactory ) - for ((index, localScope) in localScopes.withIndex()) { - processLevelForRegularInvoke( - localScope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, parentGroupForInvokeCandidates.Local(index), - ExplicitReceiverKind.EXTENSION_RECEIVER, - invokeOnGivenReceiverCandidateFactory - ) - } - - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { - // NB: companions are processed via implicitReceiverValues! - val group = parentGroupForInvokeCandidates.Implicit(depth).Member - processLevelForRegularInvoke( - implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, group, - ExplicitReceiverKind.EXTENSION_RECEIVER, - invokeOnGivenReceiverCandidateFactory - ) - } - - for ((index, topLevelScope) in topLevelScopes.withIndex()) { - processLevelForRegularInvoke( - topLevelScope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, parentGroupForInvokeCandidates.Top(index), - ExplicitReceiverKind.EXTENSION_RECEIVER, - invokeOnGivenReceiverCandidateFactory - ) - } + enumerateTowerLevels( + onLocalScope = { index, scope -> + processLevelForRegularInvoke( + scope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), + info, parentGroupForInvokeCandidates.Local(index), + ExplicitReceiverKind.EXTENSION_RECEIVER, + invokeOnGivenReceiverCandidateFactory + ) + }, + onNonLocalScope = { index, scope -> + processLevelForRegularInvoke( + scope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), + info, parentGroupForInvokeCandidates.NonLocal(index), + ExplicitReceiverKind.EXTENSION_RECEIVER, + invokeOnGivenReceiverCandidateFactory + ) + }, + onImplicitReceiver = { index, receiver -> + // NB: companions are processed via implicitReceiverValues! + val group = parentGroupForInvokeCandidates.Implicit(index).Member + processLevelForRegularInvoke( + receiver.toMemberScopeTowerLevel(extensionReceiver = invokeReceiverValue), + info, group, + ExplicitReceiverKind.EXTENSION_RECEIVER, + invokeOnGivenReceiverCandidateFactory + ) + } + ) } private suspend fun processLevelForRegularInvoke( @@ -585,7 +571,7 @@ class FirTowerResolverSession internal constructor( invokeOnGivenReceiverCandidateFactory: CandidateFactory, parentGroupForInvokeCandidates: TowerGroup ) { - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { + for ((implicitReceiverValue, depth) in implicitReceivers) { val towerGroup = parentGroupForInvokeCandidates .Implicit(depth) @@ -690,54 +676,6 @@ class FirTowerResolverSession internal constructor( ) } } - - private companion object { - private fun prepareImplicitReceivers( - implicitReceiverValues: List> - ): Pair, List> { - var depth = 0 - var firstDispatchValue = true - val explicitCompanions = mutableListOf() - val implicitReceiversUsableAsValues = mutableListOf() - val implicitReceivers = implicitReceiverValues.mapNotNull { receiverValue -> - val usableAsValue = when (receiverValue) { - is ImplicitExtensionReceiverValue -> true - is ImplicitDispatchReceiverValue -> { - val symbol = receiverValue.boundSymbol - val klass = symbol.fir as? FirRegularClass - - if (!receiverValue.implicitCompanion && klass?.isCompanion == true) { - explicitCompanions += klass.symbol - } - - if (firstDispatchValue && !receiverValue.inDelegated) { - if (!receiverValue.implicitCompanion && - klass?.isInner == false && - !symbol.classId.isLocal - ) { - firstDispatchValue = false - } - true - } else { - symbol.fir.classKind == ClassKind.OBJECT && !receiverValue.inDelegated - } - } - } - - if (receiverValue is ImplicitDispatchReceiverValue && receiverValue.implicitCompanion && receiverValue.boundSymbol in explicitCompanions) { - null - } else { - ImplicitReceiver(receiverValue, depth++, usableAsValue).also { - if (usableAsValue) { - implicitReceiversUsableAsValues.add(it) - } - } - } - } - - return implicitReceivers to implicitReceiversUsableAsValues - } - } } private fun BodyResolveComponents.createExplicitReceiverForInvoke( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerGroup.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerGroup.kt index 93f40f83718a445cf414fb439eb4815b516c7a7d..ed0990c640fafde9b819bb7aca1c768bfb911f45 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerGroup.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerGroup.kt @@ -22,12 +22,10 @@ sealed class TowerGroupKind(private val index: Int) : Comparable class Local(depth: Int) : WithDepth(40, depth) - class Implicit(depth: Int) : WithDepth(50, depth) + class ImplicitOrNonLocal(depth: Int, val kindForDebugSake: String) : WithDepth(50, depth) object InvokeExtension : TowerGroupKind(60) - class Top(depth: Int) : WithDepth(70, depth) - object Last : TowerGroupKind(Integer.MAX_VALUE) override fun compareTo(other: TowerGroupKind): Int { @@ -38,6 +36,12 @@ sealed class TowerGroupKind(private val index: Int) : Comparable } return 0 } + + companion object { + // These two groups intentionally have the same priority + fun Implicit(depth: Int): TowerGroupKind = ImplicitOrNonLocal(depth, "Implicit") + fun NonLocal(depth: Int): TowerGroupKind = ImplicitOrNonLocal(depth, "NonLocal") + } } @Suppress("FunctionName", "unused", "PropertyName") @@ -64,8 +68,7 @@ private constructor( fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth)) fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth)) - - fun Top(depth: Int) = kindOf(TowerGroupKind.Top(depth)) + fun NonLocal(depth: Int) = kindOf(TowerGroupKind.NonLocal(depth)) fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth)) @@ -79,11 +82,10 @@ private constructor( fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth)) fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth)) + fun NonLocal(depth: Int) = kindOf(TowerGroupKind.NonLocal(depth)) val InvokeExtension get() = kindOf(TowerGroupKind.InvokeExtension) - fun Top(depth: Int) = kindOf(TowerGroupKind.Top(depth)) - // Treating `a.foo()` common calls as more prioritized than `a.foo.invoke()` // It's not the same as TowerGroupKind because it's not about tower levels, but rather a different dimension semantically. // It could be implemented via another TowerGroupKind, but it's not clear what priority should be assigned to the new TowerGroupKind diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt index facd67ec88c74739293692b7ee32e32d277dfa71..9232b155f824d6b7428a08d5c47025471f10a055 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt @@ -190,8 +190,8 @@ class FirCallCompleter( lambdaArgument.replaceValueParameters(lambdaArgument.valueParameters + listOfNotNull(itParam)) lambdaArgument.replaceReturnTypeRef(expectedReturnTypeRef ?: noExpectedType) - val localContext = localContextForAnonymousFunctions.getValue(lambdaArgument.symbol) - transformer.context.withLocalContext(localContext) { + val localContext = towerDataContextForAnonymousFunctions.getValue(lambdaArgument.symbol) + transformer.context.withTowerDataContext(localContext) { lambdaArgument.transformSingle(transformer, ResolutionMode.LambdaResolution(expectedReturnTypeRef)) } transformer.context.dropContextForAnonymousFunction(lambdaArgument) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt index 3c3351ca518ac6e9974c24d56454757a65909c93..750a2361788182389cdb37d56d340521c4e2168b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt @@ -10,6 +10,7 @@ import kotlinx.collections.immutable.persistentListOf import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.* +import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ResolutionStageRunner import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer @@ -24,6 +25,8 @@ import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.sure abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAbstractPhaseTransformer(phase) { abstract val context: BodyResolveContext @@ -42,7 +45,7 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb } protected inline fun withLocalScopeCleanup(crossinline l: () -> T): T { - return context.withLocalScopesCleanup(l) + return context.withTowerDataCleanup(l) } protected fun addLocalScope(localScope: FirLocalScope?) { @@ -97,17 +100,16 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb val fileImportsScope: MutableList = mutableListOf() @set:PrivateForInline - var typeParametersScopes: FirTypeParametersScopes = persistentListOf() + lateinit var file: FirFile + internal set - @set:PrivateForInline - var localScopes: FirLocalScopes = persistentListOf() + val implicitReceiverStack: ImplicitReceiverStack get() = towerDataContext.implicitReceiverStack @set:PrivateForInline - lateinit var file: FirFile - internal set + var towerDataContext: FirTowerDataContext = FirTowerDataContext() @set:PrivateForInline - var implicitReceiverStack: MutableImplicitReceiverStack = ImplicitReceiverStackImpl() + var towerDataContextsForClassParts: FirTowerDataContextsForClassParts? = null val containerIfAny: FirDeclaration? get() = containers.lastOrNull() @@ -115,48 +117,81 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb @set:PrivateForInline var containers: PersistentList = persistentListOf() - val localContextForAnonymousFunctions: MutableMap = mutableMapOf() + val towerDataContextForAnonymousFunctions: MutableMap = mutableMapOf() @OptIn(PrivateForInline::class) - inline fun withContainer(declaration: FirDeclaration, crossinline f: () -> T): T { - val oldContainers = containers - containers = containers.add(declaration) + inline fun withNewTowerDataForClassParts(newContexts: FirTowerDataContextsForClassParts, f: () -> T): T { + val old = towerDataContextsForClassParts + + towerDataContextsForClassParts = newContexts + return try { f() } finally { - containers = oldContainers + + towerDataContextsForClassParts = old } } - @OptIn(PrivateForInline::class) - inline fun withLocalContext(localContext: FirLocalContext, f: () -> T): T { - val existedStack = this.implicitReceiverStack - val existedLocalScopes = this.localScopes + fun getTowerDataContextForStaticNestedClassesUnsafe(): FirTowerDataContext = + firTowerDataContextsForClassParts().forNestedClasses - implicitReceiverStack = localContext.implicitReceiverStack - localScopes = localContext.localScopes + fun getTowerDataContextForConstructorResolution(): FirTowerDataContext = + firTowerDataContextsForClassParts().forConstructorHeaders + fun getPrimaryConstructorParametersScope(): FirLocalScope? = + towerDataContextsForClassParts?.primaryConstructorParametersScope + + private fun firTowerDataContextsForClassParts() = + towerDataContextsForClassParts.sure { "towerDataContextForStaticNestedClasses should not be null" } + + @OptIn(PrivateForInline::class) + inline fun withContainer(declaration: FirDeclaration, crossinline f: () -> T): T { + val oldContainers = containers + containers = containers.add(declaration) return try { f() } finally { - implicitReceiverStack = existedStack - localScopes = existedLocalScopes + containers = oldContainers + } + } + + inline fun withTowerDataContext(context: FirTowerDataContext, f: () -> T): T { + return withTowerDataCleanup { + replaceTowerDataContext(context) + f() } } @OptIn(PrivateForInline::class) - inline fun withLocalScopesCleanup(l: () -> R): R { - val initialLocalScopes = localScopes + inline fun withTowerDataCleanup(l: () -> R): R { + val initialContext = towerDataContext return try { l() } finally { - localScopes = initialLocalScopes + towerDataContext = initialContext } } @OptIn(PrivateForInline::class) + fun replaceTowerDataContext(newContext: FirTowerDataContext) { + towerDataContext = newContext + } + + fun addTowerDataElement(element: FirTowerDataElement) { + replaceTowerDataContext(towerDataContext.addTowerDataElements(listOf(element))) + } + + fun addTowerDataElements(newElements: List) { + replaceTowerDataContext(towerDataContext.addTowerDataElements(newElements)) + } + fun addLocalScope(localScope: FirLocalScope) { - localScopes = localScopes.add(localScope) + replaceTowerDataContext(towerDataContext.addLocalScope(localScope)) + } + + fun addReceiver(name: Name?, implicitReceiverValue: ImplicitReceiverValue<*>) { + replaceTowerDataContext(towerDataContext.addReceiver(name, implicitReceiverValue)) } fun storeClassIfNotNested(klass: FirRegularClass) { @@ -173,21 +208,20 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb } fun saveContextForAnonymousFunction(anonymousFunction: FirAnonymousFunction) { - localContextForAnonymousFunctions[anonymousFunction.symbol] = FirLocalContext(localScopes, implicitReceiverStack.snapshot()) + towerDataContextForAnonymousFunctions[anonymousFunction.symbol] = towerDataContext } fun dropContextForAnonymousFunction(anonymousFunction: FirAnonymousFunction) { - localContextForAnonymousFunctions.remove(anonymousFunction.symbol) + towerDataContextForAnonymousFunctions.remove(anonymousFunction.symbol) } fun cleanContextForAnonymousFunction() { - localContextForAnonymousFunctions.clear() + towerDataContextForAnonymousFunctions.clear() } - @OptIn(PrivateForInline::class) private inline fun updateLastScope(transform: FirLocalScope.() -> FirLocalScope) { - val lastScope = localScopes.lastOrNull() ?: return - localScopes = localScopes.set(localScopes.size - 1, lastScope.transform()) + val lastScope = towerDataContext.localScopes.lastOrNull() ?: return + replaceTowerDataContext(towerDataContext.setLastLocalScope(lastScope.transform())) } @OptIn(PrivateForInline::class) @@ -195,13 +229,10 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb returnTypeCalculator: ReturnTypeCalculator, targetedLocalClasses: Set> ) = BodyResolveContext(returnTypeCalculator, dataFlowAnalyzerContext, targetedLocalClasses).apply { - fileImportsScope.addAll(this@BodyResolveContext.fileImportsScope) - typeParametersScopes = this@BodyResolveContext.typeParametersScopes - localScopes = this@BodyResolveContext.localScopes file = this@BodyResolveContext.file - implicitReceiverStack = this@BodyResolveContext.implicitReceiverStack - localContextForAnonymousFunctions.putAll(this@BodyResolveContext.localContextForAnonymousFunctions) + towerDataContextForAnonymousFunctions.putAll(this@BodyResolveContext.towerDataContextForAnonymousFunctions) containers = this@BodyResolveContext.containers + towerDataContext = this@BodyResolveContext.towerDataContext } } @@ -212,12 +243,12 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb val context: BodyResolveContext ) : BodyResolveComponents { override val fileImportsScope: List get() = context.fileImportsScope - override val typeParametersScopes: List get() = context.typeParametersScopes - override val localScopes: FirLocalScopes get() = context.localScopes + override val towerDataElements: List get() = context.towerDataContext.towerDataElements + override val localScopes: FirLocalScopes get() = context.towerDataContext.localScopes override val file: FirFile get() = context.file override val implicitReceiverStack: ImplicitReceiverStack get() = context.implicitReceiverStack override val containingDeclarations: List get() = context.containers - override val localContextForAnonymousFunctions: LocalContextForAnonymousFunctions get() = context.localContextForAnonymousFunctions + override val towerDataContextForAnonymousFunctions: TowerDataContextForAnonymousFunctions get() = context.towerDataContextForAnonymousFunctions override val returnTypeCalculator: ReturnTypeCalculator get() = context.returnTypeCalculator override val container: FirDeclaration get() = context.containerIfAny!! diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt index 44bff5a56457e10b330fd60935c2464e97970721..52c11d01ab7babf8b335d6e51749674d284311f8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.asTowerDataElement import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve @@ -50,6 +51,8 @@ open class FirBodyResolveTransformer( return withScopeCleanup(context.fileImportsScope) { val importingScopes = createImportingScopes(file, session, components.scopeSession) context.fileImportsScope += importingScopes + context.addTowerDataElements(importingScopes.map { it.asTowerDataElement(isLocal = false) }) + file.replaceResolvePhase(transformerPhase) @Suppress("UNCHECKED_CAST") transformDeclarationContent(file, data) as CompositeTransformResult diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index bb5aac506419ed92f44e4a16510d922db0cee447..64203b5c57d129bea63d2d87237519e927f200b7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -5,13 +5,15 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve -import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirFunctionTarget +import org.jetbrains.kotlin.fir.copy import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty -import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.buildReturnExpression import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression @@ -19,10 +21,12 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.impl.FirEmptyControlFlowGraphReference import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate +import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue import org.jetbrains.kotlin.fir.resolve.inference.FirDelegatedPropertyInferenceSession import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.transformers.* +import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType @@ -35,8 +39,6 @@ import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.Name open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) { - private var primaryConstructorParametersScope: FirLocalScope? = null - private var containingClass: FirRegularClass? = null private fun transformDeclarationContent( @@ -66,22 +68,23 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor } } - protected inline fun withTypeParametersOf(declaration: FirMemberDeclaration, crossinline l: () -> T): T { - if (declaration.typeParameters.isEmpty()) return l() + protected fun createTypeParameterScope(declaration: FirMemberDeclaration): FirMemberTypeParameterScope? { + if (declaration.typeParameters.isEmpty()) return null for (typeParameter in declaration.typeParameters) { (typeParameter as? FirTypeParameter)?.replaceResolvePhase(FirResolvePhase.STATUS) typeParameter.transformChildren(transformer, ResolutionMode.ContextIndependent) } - val before = context.typeParametersScopes - @OptIn(PrivateForInline::class) - context.typeParametersScopes = context.typeParametersScopes.add(FirMemberTypeParameterScope(declaration)) - return try { + return FirMemberTypeParameterScope(declaration) + } + + protected inline fun withTypeParametersOf(declaration: FirMemberDeclaration, crossinline l: () -> T): T { + val scope = createTypeParameterScope(declaration) ?: return l() + + return context.withTowerDataCleanup { + context.addTowerDataElement(scope.asTowerDataElement(isLocal = false)) l() - } finally { - @OptIn(PrivateForInline::class) - context.typeParametersScopes = before } } @@ -111,11 +114,11 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor withLocalScopeCleanup { context.withContainer(property) { if (property.delegate != null) { - addLocalScope(primaryConstructorParametersScope) + addLocalScope(context.getPrimaryConstructorParametersScope()) transformPropertyWithDelegate(property) } else { withLocalScopeCleanup { - addLocalScope(primaryConstructorParametersScope) + addLocalScope(context.getPrimaryConstructorParametersScope()) property.transformChildrenWithoutAccessors(returnTypeRef) property.transformInitializer(integerLiteralTypeApproximator, null) } @@ -323,8 +326,13 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor return regularClass.runAllPhasesForLocalClass(transformer, components, data).compose() } + return context.withTowerDataCleanup { + if (!regularClass.isInner && context.containerIfAny is FirRegularClass) { + context.replaceTowerDataContext( + context.getTowerDataContextForStaticNestedClassesUnsafe() + ) + } - return withTypeParametersOf(regularClass) { doTransformRegularClass(regularClass, data) } } @@ -339,20 +347,10 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor dataFlowAnalyzer.enterClass() } - val oldConstructorScope = primaryConstructorParametersScope val oldContainingClass = containingClass - primaryConstructorParametersScope = null containingClass = regularClass val type = regularClass.defaultType() - val result = withLabelAndReceiverType(regularClass.name, regularClass, type) { - val constructor = regularClass.declarations.firstOrNull() as? FirConstructor - if (constructor?.isPrimary == true) { - primaryConstructorParametersScope = FirLocalScope().let { - var scope = it - constructor.valueParameters.forEach { scope = scope.storeVariable(it) } - scope - } - } + val result = withScopesForClass(regularClass.name, regularClass, type) { transformDeclarationContent(regularClass, data).single as FirRegularClass } @@ -366,7 +364,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor } containingClass = oldContainingClass - primaryConstructorParametersScope = oldConstructorScope return (@Suppress("UNCHECKED_CAST") result.compose()) } @@ -386,7 +383,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor this.type = type } } - var result = withLabelAndReceiverType(null, anonymousObject, type) { + var result = withScopesForClass(null, anonymousObject, type) { transformDeclarationContent(anonymousObject, data).single as FirAnonymousObject } if (!implicitTypeOnly && result.controlFlowGraphReference == FirEmptyControlFlowGraphReference) { @@ -521,9 +518,10 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor if (implicitTypeOnly) return anonymousInitializer.compose() return withLocalScopeCleanup { dataFlowAnalyzer.enterInitBlock(anonymousInitializer) - addLocalScope(primaryConstructorParametersScope) + addLocalScope(context.getPrimaryConstructorParametersScope()) addLocalScope(FirLocalScope()) - val result = transformDeclarationContent(anonymousInitializer, ResolutionMode.ContextIndependent).single as FirAnonymousInitializer + val result = + transformDeclarationContent(anonymousInitializer, ResolutionMode.ContextIndependent).single as FirAnonymousInitializer val graph = dataFlowAnalyzer.exitInitBlock(result) result.transformControlFlowGraphReference(ControlFlowGraphReferenceTransformer, graph).compose() } @@ -683,27 +681,79 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor return this } + private inline fun withScopesForClass( + labelName: Name?, + owner: FirClass<*>, + type: ConeKotlinType, + block: () -> T + ): T = context.withTowerDataCleanup { + val towerElementsForClass = components.collectTowerDataElementsForClass(owner, type) + + val staticsAndCompanion = + context.towerDataContext + .addTowerDataElements(towerElementsForClass.superClassesStaticsAndCompanionReceivers) + .run { + if (towerElementsForClass.companionReceiver != null) + addReceiver(null, towerElementsForClass.companionReceiver) + else + this + } + .addNonLocalScopeIfNotNull(towerElementsForClass.companionStaticScope) + .addNonLocalScopeIfNotNull(towerElementsForClass.staticScope) + + val typeParameterScope = (owner as? FirRegularClass)?.let(this::createTypeParameterScope) + + val forMembersResolution = + staticsAndCompanion + .addReceiver(labelName, towerElementsForClass.thisReceiver) + .addNonLocalScopeIfNotNull(typeParameterScope) + + val scopeForConstructorHeader = + staticsAndCompanion.addNonLocalScopeIfNotNull(typeParameterScope) + + val newTowerDataContextForStaticNestedClasses = + if ((owner as? FirRegularClass)?.classKind?.isSingleton == true) + forMembersResolution + else + staticsAndCompanion + + val constructor = (owner as? FirRegularClass)?.declarations?.firstOrNull() as? FirConstructor + val primaryConstructorParametersScope = + if (constructor?.isPrimary == true) { + constructor.valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) } + } else null + + components.context.replaceTowerDataContext(forMembersResolution) + + val newContexts = + FirTowerDataContextsForClassParts( + newTowerDataContextForStaticNestedClasses, + scopeForConstructorHeader, + primaryConstructorParametersScope + ) + + context.withNewTowerDataForClassParts(newContexts) { + block() + } + } + protected inline fun withLabelAndReceiverType( labelName: Name?, - owner: FirDeclaration, + owner: FirCallableDeclaration<*>, type: ConeKotlinType?, block: () -> T - ): T { - val (implicitReceiverValue, implicitCompanionValues) = components.collectImplicitReceivers(type, owner) - implicitCompanionValues.forEach { value -> - context.implicitReceiverStack.add(null, value) + ): T = context.withTowerDataCleanup { + if (type != null) { + val receiver = ImplicitExtensionReceiverValue( + owner.symbol, + type, + components.session, + components.scopeSession + ) + context.addReceiver(labelName, receiver) } - implicitReceiverValue?.let { context.implicitReceiverStack.add(labelName, it) } - try { - return block() - } finally { - if (type != null) { - context.implicitReceiverStack.pop(labelName) - for (i in implicitCompanionValues.indices) - context.implicitReceiverStack.pop(null) - } - } + block() } private fun storeVariableReturnType(variable: FirVariable<*>) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index fb88af6019ec73d925cd5eff70aac75c6dd1c863..6aff6c15c17b4821d35e0ce845af4e79d45af90e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -9,9 +9,9 @@ import com.intellij.openapi.progress.ProcessCanceledException import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall @@ -309,7 +309,8 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : } else -> buildErrorExpression { source = operatorCall.source - diagnostic = ConeOperatorAmbiguityError(listOf(operatorCallReference.resolvedSymbol, assignCallReference.resolvedSymbol)) + diagnostic = + ConeOperatorAmbiguityError(listOf(operatorCallReference.resolvedSymbol, assignCallReference.resolvedSymbol)) }.compose() } } @@ -541,7 +542,8 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : FirConstKind.Float -> constructLiteralType(StandardClassIds.Float) FirConstKind.Double -> constructLiteralType(StandardClassIds.Double) FirConstKind.IntegerLiteral, FirConstKind.UnsignedIntegerLiteral -> { - val integerLiteralType = ConeIntegerLiteralTypeImpl(constExpression.value as Long, isUnsigned = kind == FirConstKind.UnsignedIntegerLiteral) + val integerLiteralType = + ConeIntegerLiteralTypeImpl(constExpression.value as Long, isUnsigned = kind == FirConstKind.UnsignedIntegerLiteral) val expectedType = data.expectedType?.coneTypeSafe() if (expectedType != null) { val approximatedType = integerLiteralType.getApproximatedType(expectedType) @@ -633,15 +635,13 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : var result = delegatedConstructorCall try { val lastDispatchReceiver = implicitReceiverStack.lastDispatchReceiver() - val name = lastDispatchReceiver?.boundSymbol?.classId?.shortClassName - if (lastDispatchReceiver != null) { - context.implicitReceiverStack.pop(name) - context.implicitReceiverStack.add(name, lastDispatchReceiver.copyForDelegated()) - } - delegatedConstructorCall.transformChildren(transformer, ResolutionMode.ContextDependent) - if (lastDispatchReceiver != null) { - context.implicitReceiverStack.pop(name) - context.implicitReceiverStack.add(name, lastDispatchReceiver) + context.withTowerDataCleanup { + if ((context.containerIfAny as? FirConstructor)?.isPrimary == true) { + context.replaceTowerDataContext(context.getTowerDataContextForConstructorResolution()) + context.getPrimaryConstructorParametersScope()?.let(context::addLocalScope) + } + + delegatedConstructorCall.transformChildren(transformer, ResolutionMode.ContextDependent) } val typeArguments: List val reference = delegatedConstructorCall.calleeReference @@ -700,7 +700,10 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : } @OptIn(ExperimentalStdlibApi::class) - override fun transformAugmentedArraySetCall(augmentedArraySetCall: FirAugmentedArraySetCall, data: ResolutionMode): CompositeTransformResult { + override fun transformAugmentedArraySetCall( + augmentedArraySetCall: FirAugmentedArraySetCall, + data: ResolutionMode + ): CompositeTransformResult { assert(augmentedArraySetCall.operation in FirOperation.ASSIGNMENTS) assert(augmentedArraySetCall.operation != FirOperation.ASSIGN) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeResolveScopeForBodyResolve.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeResolveScopeForBodyResolve.kt index 1d4502cf2b67b461c9de223420474c7d1afb6bd3..ff9179aa479ff135ba52de50a0c13274ee032e6b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeResolveScopeForBodyResolve.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeResolveScopeForBodyResolve.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents -import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue import org.jetbrains.kotlin.fir.scopes.FirIterableScope import org.jetbrains.kotlin.fir.scopes.FirScope @@ -18,12 +17,4 @@ class FirTypeResolveScopeForBodyResolve( } fun BodyResolveComponents.createCurrentScopeList(): List = - mutableListOf().apply { - addAll(localScopes.asReversed()) - implicitReceiverStack.receiversAsReversed().mapNotNullTo(this) { - (it as? ImplicitDispatchReceiverValue)?.implicitScope - } - - addAll(typeParametersScopes.asReversed()) - addAll(fileImportsScope.asReversed()) - } + towerDataElements.asReversed().mapNotNull { it.scope }