FIR: extract BodyResolveContext.withConstructor in variations

This commit is contained in:
Mikhail Glukhikh
2021-03-05 14:12:48 +03:00
parent bd2cdf2ec9
commit d7b2ab6b99
3 changed files with 88 additions and 66 deletions
@@ -132,7 +132,7 @@ class ImplicitExtensionReceiverValue(
) : ImplicitReceiverValue<FirCallableSymbol<*>>(boundSymbol, type, useSiteSession, scopeSession)
class InaccessibleImplicitReceiverValue internal constructor(
class InaccessibleImplicitReceiverValue(
boundSymbol: FirClassSymbol<*>,
type: ConeKotlinType,
useSiteSession: FirSession,
@@ -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 <T> withConstructor(constructor: FirConstructor, crossinline f: () -> T): T =
withContainer(constructor, f)
inline fun <T> 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 <T> forDelegatedConstructor(
constructor: FirConstructor,
parametersScope: FirLocalScope? = buildConstructorParametersScope(constructor),
crossinline f: () -> T
): T {
if (parametersScope == null) return f()
return withTowerDataCleanup {
addLocalScope(parametersScope)
f()
}
}
inline fun <T> 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) }
}
@@ -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<FirConstructor> {
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 <T> withLabelAndReceiverType(
labelName: Name?,
owner: FirCallableDeclaration<*>,