From d7b2ab6b99a6d3fc8abe58754e3aaf65ff5421f8 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 5 Mar 2021 14:12:48 +0300 Subject: [PATCH] FIR: extract BodyResolveContext.withConstructor in variations --- .../kotlin/fir/resolve/calls/FirReceivers.kt | 2 +- .../body/resolve/BodyResolveContext.kt | 69 +++++++++++++++ .../FirDeclarationsResolveTransformer.kt | 83 ++++--------------- 3 files changed, 88 insertions(+), 66 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt index d0a0e3c4dab..87e3f5c15ef 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt @@ -132,7 +132,7 @@ class ImplicitExtensionReceiverValue( ) : ImplicitReceiverValue>(boundSymbol, type, useSiteSession, scopeSession) -class InaccessibleImplicitReceiverValue internal constructor( +class InaccessibleImplicitReceiverValue( boundSymbol: FirClassSymbol<*>, type: ConeKotlinType, useSiteSession: FirSession, 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 007a905216b..8335a94d7b8 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 @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue +import org.jetbrains.kotlin.fir.resolve.calls.InaccessibleImplicitReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext import org.jetbrains.kotlin.fir.resolve.dfa.PersistentFlow @@ -490,4 +491,72 @@ class BodyResolveContext( if (typeParameters.isEmpty()) return null return FirMemberTypeParameterScope(this) } + + inline fun withConstructor(constructor: FirConstructor, crossinline f: () -> T): T = + withContainer(constructor, f) + + inline fun forConstructorParameters( + constructor: FirConstructor, + owningClass: FirRegularClass?, + holder: SessionHolder, + crossinline f: () -> T + ): T { + // Default values of constructor can't access members of constructing class + return withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { + if (owningClass != null && !constructor.isPrimary) { + addReceiver( + null, + InaccessibleImplicitReceiverValue( + owningClass.symbol, + owningClass.defaultType(), + holder.session, + holder.scopeSession + ) + ) + } + withTowerDataCleanup { + addLocalScope(FirLocalScope()) + f() + } + } + } + + inline fun forDelegatedConstructor( + constructor: FirConstructor, + parametersScope: FirLocalScope? = buildConstructorParametersScope(constructor), + crossinline f: () -> T + ): T { + if (parametersScope == null) return f() + return withTowerDataCleanup { + addLocalScope(parametersScope) + f() + } + } + + inline fun forConstructorBody( + constructor: FirConstructor, + parametersScope: FirLocalScope? = buildConstructorParametersScope(constructor), + crossinline f: () -> T + ): T { + return if (constructor.isPrimary) { + /* + * Primary constructor may have body only if class delegates implementation to some property + * In it's body we don't have this receiver for building class, so we need to use + * special towerDataContext + */ + withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { + parametersScope?.let { addLocalScope(it) } + f() + } + } else { + withTowerDataCleanup { + parametersScope?.let { addLocalScope(it) } + f() + } + } + } + + fun buildConstructorParametersScope(constructor: FirConstructor): FirLocalScope? = + if (constructor.isPrimary) getPrimaryConstructorAllParametersScope() + else constructor.valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) } } 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 9b363b351fb..bd69f6778a5 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 @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference 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.calls.InaccessibleImplicitReceiverValue import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType @@ -568,74 +567,32 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor private fun doTransformConstructor(constructor: FirConstructor, data: ResolutionMode): CompositeTransformResult { val owningClass = context.containerIfAny as? FirRegularClass - return context.withContainer(constructor) { - transformer.replaceDeclarationResolvePhaseIfNeeded(constructor, transformerPhase) - dataFlowAnalyzer.enterFunction(constructor) - constructor.transformTypeParameters(transformer, data) - .transformAnnotations(transformer, data) - .transformReceiverTypeRef(transformer, data) - .transformReturnTypeRef(transformer, data) + transformer.replaceDeclarationResolvePhaseIfNeeded(constructor, transformerPhase) + dataFlowAnalyzer.enterFunction(constructor) - /* - * Default values of constructor can't access members of constructing class - */ - context.withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { - if (owningClass != null && !constructor.isPrimary) { - context.addReceiver( - null, - InaccessibleImplicitReceiverValue( - owningClass.symbol, - owningClass.defaultType(), - session, - scopeSession - ) - ) - } - withNewLocalScope { - constructor.transformValueParameters(transformer, data) - } + constructor.transformTypeParameters(transformer, data) + .transformAnnotations(transformer, data) + .transformReceiverTypeRef(transformer, data) + .transformReturnTypeRef(transformer, data) + + context.withConstructor(constructor) { + context.forConstructorParameters(constructor, owningClass, components) { + constructor.transformValueParameters(transformer, data) } - - val scopeWithValueParameters = if (constructor.isPrimary) { - context.getPrimaryConstructorAllParametersScope() - } else { - constructor.scopeWithParameters() - } - - /* - * Delegated constructor call is called before constructor body, so we need to - * analyze it before body, so body can access smartcasts from that call - */ - withLocalScope(scopeWithValueParameters) { + val parametersScope = context.buildConstructorParametersScope(constructor) + context.forDelegatedConstructor(constructor, parametersScope) { constructor.transformDelegatedConstructor(transformer, data) } - - if (constructor.body != null) { - if (constructor.isPrimary) { - /* - * Primary constructor may have body only if class delegates implementation to some property - * In it's body we don't have this receiver for building class, so we need to use - * special towerDataContext - */ - context.withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { - addLocalScope(scopeWithValueParameters) - constructor.transformBody(transformer, data) - } - } else { - withLocalScopeCleanup { - addLocalScope(scopeWithValueParameters) - constructor.transformBody(transformer, data) - } - } + context.forConstructorBody(constructor, parametersScope) { + constructor.transformBody(transformer, data) } - - val controlFlowGraphReference = dataFlowAnalyzer.exitFunction(constructor) - constructor.replaceControlFlowGraphReference(controlFlowGraphReference) - constructor.compose() } - } + val controlFlowGraphReference = dataFlowAnalyzer.exitFunction(constructor) + constructor.replaceControlFlowGraphReference(controlFlowGraphReference) + return constructor.compose() + } override fun transformAnonymousInitializer( anonymousInitializer: FirAnonymousInitializer, @@ -843,10 +800,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor return this } - private fun FirConstructor.scopeWithParameters(): FirLocalScope { - return valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) } - } - protected inline fun withLabelAndReceiverType( labelName: Name?, owner: FirCallableDeclaration<*>,