From 130e3552ea10f2c6bc5eb7b53aba755f2ae9923b Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 1 Mar 2021 16:52:02 +0300 Subject: [PATCH] Unite different tower contexts in FirTowerDataContextsForClassParts --- .../jetbrains/kotlin/fir/FirCallResolver.kt | 2 +- .../fir/resolve/BodyResolveComponents.kt | 57 ++++++++++-- .../fir/resolve/inference/FirCallCompleter.kt | 2 +- .../body/resolve/BodyResolveContext.kt | 86 ++++++++++--------- .../FirAbstractBodyResolveTransformer.kt | 8 ++ .../FirDeclarationsResolveTransformer.kt | 32 +++---- .../FirExpressionsResolveTransformer.kt | 29 +++---- 7 files changed, 135 insertions(+), 81 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index 4c4821fd24b..845ff7fbe16 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -253,7 +253,7 @@ class FirCallResolver( val towerDataContext = transformer.context.towerDataContextForCallableReferences[callableReferenceAccess] ?: transformer.context.towerDataContext - val result = transformer.context.withTowerDataContext(towerDataContext) { + val result = transformer.context.withSpecialTowerDataContext(towerDataContext) { towerResolver.runResolver( info, transformer.resolutionContext, 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 27af854fac4..cbf6d23861e 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 @@ -10,6 +10,7 @@ import kotlinx.collections.immutable.persistentListOf import org.jetbrains.kotlin.fir.FirCallResolver import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.resolve.FirTowerDataMode.* import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue @@ -27,6 +28,7 @@ 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 +import java.util.* interface SessionHolder { val session: FirSession @@ -141,13 +143,56 @@ fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement = typealias TowerDataContextForAnonymousFunctions = Map +enum class FirTowerDataMode { + MEMBER_DECLARATION, + NESTED_CLASS, + COMPANION_OBJECT, + CONSTRUCTOR_HEADER, + SPECIAL, +} + class FirTowerDataContextsForClassParts( - val forNestedClasses: FirTowerDataContext, - val forCompanionObject: FirTowerDataContext, - val forConstructorHeaders: FirTowerDataContext, - val primaryConstructorPureParametersScope: FirLocalScope?, - val primaryConstructorAllParametersScope: FirLocalScope?, -) + forMemberDeclarations: FirTowerDataContext, + forNestedClasses: FirTowerDataContext? = null, + forCompanionObject: FirTowerDataContext? = null, + forConstructorHeaders: FirTowerDataContext? = null, + val primaryConstructorPureParametersScope: FirLocalScope? = null, + val primaryConstructorAllParametersScope: FirLocalScope? = null, +) { + private val modeMap = EnumMap(FirTowerDataMode::class.java) + + init { + modeMap[MEMBER_DECLARATION] = forMemberDeclarations + modeMap[NESTED_CLASS] = forNestedClasses + modeMap[COMPANION_OBJECT] = forCompanionObject + modeMap[CONSTRUCTOR_HEADER] = forConstructorHeaders + } + + var mode: FirTowerDataMode = MEMBER_DECLARATION + + val forMemberDeclaration: FirTowerDataContext get() = modeMap.getValue(MEMBER_DECLARATION) + val forNestedClasses: FirTowerDataContext get() = modeMap.getValue(NESTED_CLASS) + val forCompanionObject: FirTowerDataContext get() = modeMap.getValue(COMPANION_OBJECT) + val forConstructorHeaders: FirTowerDataContext get() = modeMap.getValue(CONSTRUCTOR_HEADER) + + var special: FirTowerDataContext + get() = modeMap.getValue(SPECIAL) + set(value) { + mode = SPECIAL + modeMap[SPECIAL] = value + } + var currentContext: FirTowerDataContext + get() = modeMap.getValue(mode) + set(value) { + modeMap[mode] = value + } + + fun withMemberDeclarationContext(newContextForMemberDeclarations: FirTowerDataContext): FirTowerDataContextsForClassParts = + FirTowerDataContextsForClassParts( + newContextForMemberDeclarations, modeMap[NESTED_CLASS], modeMap[COMPANION_OBJECT], modeMap[CONSTRUCTOR_HEADER], + primaryConstructorPureParametersScope, primaryConstructorAllParametersScope + ) +} // --------------------------------------- Utils --------------------------------------- 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 4c87b561a9e..afc8734e05f 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 @@ -223,7 +223,7 @@ class FirCallCompleter( } val localContext = components.towerDataContextForAnonymousFunctions[lambdaArgument.symbol] ?: error("") - transformer.context.withTowerDataContext(localContext) { + transformer.context.withSpecialTowerDataContext(localContext) { if (builderInferenceSession != null) { transformer.context.withInferenceSession(builderInferenceSession) { lambdaArgument.transformSingle(transformer, ResolutionMode.LambdaResolution(expectedReturnTypeRef)) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index ff6c54ebcc8..5840d7242ac 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -10,10 +10,7 @@ import kotlinx.collections.immutable.persistentListOf import org.jetbrains.kotlin.fir.PrivateForInline import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess -import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext -import org.jetbrains.kotlin.fir.resolve.FirTowerDataContextsForClassParts -import org.jetbrains.kotlin.fir.resolve.FirTowerDataElement -import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext import org.jetbrains.kotlin.fir.resolve.dfa.PersistentFlow @@ -25,7 +22,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.utils.sure class BodyResolveContext( val returnTypeCalculator: ReturnTypeCalculator, @@ -41,11 +37,12 @@ class BodyResolveContext( val implicitReceiverStack: ImplicitReceiverStack get() = towerDataContext.implicitReceiverStack - @set:PrivateForInline - var towerDataContext: FirTowerDataContext = FirTowerDataContext() + val towerDataContext: FirTowerDataContext + get() = towerDataContextsForClassParts.currentContext @set:PrivateForInline - var towerDataContextsForClassParts: FirTowerDataContextsForClassParts? = null + var towerDataContextsForClassParts: FirTowerDataContextsForClassParts = + FirTowerDataContextsForClassParts(forMemberDeclarations = FirTowerDataContext()) val containerIfAny: FirDeclaration? get() = containers.lastOrNull() @@ -84,23 +81,11 @@ class BodyResolveContext( } } - fun getTowerDataContextForStaticNestedClassesUnsafe(): FirTowerDataContext = - firTowerDataContextsForClassParts().forNestedClasses - - fun getTowerDataContextForCompanionUnsafe(): FirTowerDataContext = - firTowerDataContextsForClassParts().forCompanionObject - - fun getTowerDataContextForConstructorResolution(): FirTowerDataContext = - firTowerDataContextsForClassParts().forConstructorHeaders - fun getPrimaryConstructorPureParametersScope(): FirLocalScope? = - towerDataContextsForClassParts?.primaryConstructorPureParametersScope + towerDataContextsForClassParts.primaryConstructorPureParametersScope fun getPrimaryConstructorAllParametersScope(): FirLocalScope? = - towerDataContextsForClassParts?.primaryConstructorAllParametersScope - - private fun firTowerDataContextsForClassParts() = - towerDataContextsForClassParts.sure { "towerDataContextForStaticNestedClasses should not be null" } + towerDataContextsForClassParts.primaryConstructorAllParametersScope @OptIn(PrivateForInline::class) inline fun withContainer(declaration: FirDeclaration, crossinline f: () -> T): T { @@ -113,20 +98,36 @@ class BodyResolveContext( } } - inline fun withTowerDataContext(context: FirTowerDataContext, f: () -> T): T { - return withTowerDataCleanup { - replaceTowerDataContext(context) - f() - } - } - @OptIn(PrivateForInline::class) inline fun withTowerDataCleanup(l: () -> R): R { val initialContext = towerDataContext return try { l() } finally { - towerDataContext = initialContext + replaceTowerDataContext(initialContext) + } + } + + inline fun withTowerDataMode(mode: FirTowerDataMode, f: () -> T): T { + return withTowerModeCleanup { + towerDataMode = mode + f() + } + } + + inline fun withSpecialTowerDataContext(context: FirTowerDataContext, f: () -> T): T { + return withTowerModeCleanup { + towerDataContextsForClassParts.special = context + f() + } + } + + inline fun withTowerModeCleanup(l: () -> R): R { + val initialMode = towerDataMode + return try { + l() + } finally { + towerDataMode = initialMode } } @@ -140,9 +141,15 @@ class BodyResolveContext( } } + var towerDataMode: FirTowerDataMode + get() = towerDataContextsForClassParts.mode + set(value) { + towerDataContextsForClassParts.mode = value + } + @OptIn(PrivateForInline::class) fun replaceTowerDataContext(newContext: FirTowerDataContext) { - towerDataContext = newContext + towerDataContextsForClassParts.currentContext = newContext } fun addNonLocalTowerDataElement(element: FirTowerDataElement) { @@ -199,12 +206,13 @@ class BodyResolveContext( fun createSnapshotForLocalClasses( returnTypeCalculator: ReturnTypeCalculator, targetedLocalClasses: Set> - ): BodyResolveContext = BodyResolveContext(returnTypeCalculator, dataFlowAnalyzerContext, targetedLocalClasses, outerLocalClassForNested).apply { - file = this@BodyResolveContext.file - towerDataContextForAnonymousFunctions.putAll(this@BodyResolveContext.towerDataContextForAnonymousFunctions) - towerDataContextForCallableReferences.putAll(this@BodyResolveContext.towerDataContextForCallableReferences) - containers = this@BodyResolveContext.containers - towerDataContext = this@BodyResolveContext.towerDataContext - anonymousFunctionsAnalyzedInDependentContext.addAll(this@BodyResolveContext.anonymousFunctionsAnalyzedInDependentContext) - } + ): BodyResolveContext = + BodyResolveContext(returnTypeCalculator, dataFlowAnalyzerContext, targetedLocalClasses, outerLocalClassForNested).apply { + file = this@BodyResolveContext.file + towerDataContextForAnonymousFunctions.putAll(this@BodyResolveContext.towerDataContextForAnonymousFunctions) + towerDataContextForCallableReferences.putAll(this@BodyResolveContext.towerDataContextForCallableReferences) + containers = this@BodyResolveContext.containers + replaceTowerDataContext(this@BodyResolveContext.towerDataContext) + anonymousFunctionsAnalyzedInDependentContext.addAll(this@BodyResolveContext.anonymousFunctionsAnalyzedInDependentContext) + } } 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 401ae73af04..83969415d4f 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 @@ -51,6 +51,14 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb } } + protected inline fun withLocalScope(localScope: FirLocalScope?, crossinline l: () -> T): T { + if (localScope == null) return l() + return context.withTowerDataCleanup { + addLocalScope(localScope) + l() + } + } + protected fun addNewLocalScope() { context.addLocalScope(FirLocalScope()) } 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 1f80b35ff1c..e2d197372a2 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 @@ -115,7 +115,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor } override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): CompositeTransformResult { - context.withTowerDataContext(context.getTowerDataContextForConstructorResolution()) { + context.withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { return (enumEntry.transformChildren(this, data) as FirEnumEntry).compose() } } @@ -185,7 +185,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor return withFullBodyResolve { withLocalScopeCleanup { val primaryConstructorParametersScope = context.getPrimaryConstructorAllParametersScope() - context.withTowerDataContext(context.getTowerDataContextForConstructorResolution()) { + context.withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { context.withContainer(field) { withLocalScopeCleanup { addLocalScope(primaryConstructorParametersScope) @@ -400,15 +400,13 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor return regularClass.runAllPhasesForLocalClass(transformer, components, data).compose() } - return context.withTowerDataCleanup { + return context.withTowerModeCleanup { if (!regularClass.isInner && context.containerIfAny is FirRegularClass) { - context.replaceTowerDataContext( - if (regularClass.isCompanion) { - context.getTowerDataContextForCompanionUnsafe() - } else { - context.getTowerDataContextForStaticNestedClassesUnsafe() - } - ) + if (regularClass.isCompanion) { + context.towerDataMode = FirTowerDataMode.COMPANION_OBJECT + } else { + context.towerDataMode = FirTowerDataMode.NESTED_CLASS + } } doTransformRegularClass(regularClass, data) @@ -642,7 +640,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor /* * Default values of constructor can't access members of constructing class */ - context.withTowerDataContext(context.getTowerDataContextForConstructorResolution()) { + context.withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { if (owningClass != null && !constructor.isPrimary) { context.addReceiver( null, @@ -669,8 +667,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor * Delegated constructor call is called before constructor body, so we need to * analyze it before body, so body can access smartcasts from that call */ - context.withTowerDataCleanup { - addLocalScope(scopeWithValueParameters) + withLocalScope(scopeWithValueParameters) { constructor.transformDelegatedConstructor(transformer, data) } @@ -681,7 +678,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor * In it's body we don't have this receiver for building class, so we need to use * special towerDataContext */ - context.withTowerDataContext(context.getTowerDataContextForConstructorResolution()) { + context.withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { addLocalScope(scopeWithValueParameters) constructor.transformBody(transformer, data) } @@ -914,7 +911,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor owner: FirClass<*>, type: ConeKotlinType, block: () -> T - ): T = context.withTowerDataCleanup { + ): T { val towerElementsForClass = components.collectTowerDataElementsForClass(owner, type) val base = context.towerDataContext.addNonLocalTowerDataElements(towerElementsForClass.superClassesStaticsAndCompanionReceivers) @@ -952,9 +949,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor null to null } - components.context.replaceTowerDataContext(forMembersResolution) - val newContexts = FirTowerDataContextsForClassParts( + forMembersResolution, newTowerDataContextForStaticNestedClasses, statics, scopeForConstructorHeader, @@ -962,7 +958,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor primaryConstructorAllParametersScope ) - context.withNewTowerDataForClassParts(newContexts) { + return context.withNewTowerDataForClassParts(newContexts) { block() } } 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 3e542a3109e..01e42f6c8a5 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 @@ -827,24 +827,21 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform var result = delegatedConstructorCall try { val lastDispatchReceiver = implicitReceiverStack.lastDispatchReceiver() - context.withTowerDataCleanup { - if ((context.containerIfAny as? FirConstructor)?.isPrimary == true) { - context.replaceTowerDataContext(context.getTowerDataContextForConstructorResolution()) - context.getPrimaryConstructorAllParametersScope()?.let(context::addLocalScope) - } - // it's just a constructor parameters scope created in - // `FirDeclarationResolveTransformer::doTransformConstructor()` - val parametersScope = context.towerDataContext.localScopes.lastOrNull() - - // because there's a `context.saveContextForAnonymousFunction(anonymousFunction)` - // call inside of the FirDeclarationResolveTransformer and accessing `this` - // inside a lambda which is a value parameter of a constructor delegate - // is prohibited - context.withTowerDataContext(context.getTowerDataContextForConstructorResolution()) { - parametersScope?.let { - addLocalScope(it) + // because there's a `context.saveContextForAnonymousFunction(anonymousFunction)` + // call inside of the FirDeclarationResolveTransformer and accessing `this` + // inside a lambda which is a value parameter of a constructor delegate + // is prohibited + context.withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { + context.withTowerDataCleanup { + if ((context.containerIfAny as? FirConstructor)?.isPrimary == true) { + context.getPrimaryConstructorAllParametersScope()?.let(context::addLocalScope) } + + // it's just a constructor parameters scope created in + // `FirDeclarationResolveTransformer::doTransformConstructor()` + context.towerDataContextsForClassParts.forMemberDeclaration.localScopes.lastOrNull()?.let(context::addLocalScope) + if (containingClass is FirRegularClass && !containingConstructor.isPrimary) { context.addReceiver( null,