[FIR] Move local scopes immutable

This commit is contained in:
Dmitriy Novozhilov
2020-03-03 12:28:23 +03:00
parent 25dc9f948a
commit 50742a4686
10 changed files with 202 additions and 92 deletions
@@ -30,8 +30,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.transformers.phasedFir
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -42,9 +40,7 @@ import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
class FirCallResolver(
components: BodyResolveComponents,
topLevelScopes: List<FirScope>,
localScopes: List<FirLocalScope>,
private val components: BodyResolveComponents,
private val qualifiedResolver: FirQualifiedNameResolver,
) : BodyResolveComponents by components {
@@ -55,9 +51,7 @@ class FirCallResolver(
}
private val towerResolver = FirTowerResolver(
returnTypeCalculator, this, resolutionStageRunner,
topLevelScopes = topLevelScopes.asReversed(),
localScopes = localScopes.asReversed(),
returnTypeCalculator, components, resolutionStageRunner,
)
private val conflictResolver =
@@ -5,7 +5,10 @@
package org.jetbrains.kotlin.fir.resolve
import kotlinx.collections.immutable.*
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -91,32 +94,3 @@ class ImplicitReceiverStackImpl private constructor(
return ImplicitReceiverStackImpl(stack, originalTypes, indexesPerLabel, indexesPerSymbol)
}
}
class PersistentSetMultimap<K, V> private constructor(private val map: PersistentMap<K, PersistentSet<V>>) {
constructor() : this(persistentMapOf())
fun put(key: K, value: V): PersistentSetMultimap<K, V> {
val set = map[key] ?: persistentSetOf()
val newSet = set.add(value)
if (newSet === set) return this
val newMap = map.put(key, newSet)
return PersistentSetMultimap(newMap)
}
fun remove(key: K, value: V): PersistentSetMultimap<K, V> {
val set = map.get(key) ?: return this
val newSet = set.remove(value)
if (set === newSet) return this
val newMap = if (newSet.isEmpty()) {
map.remove(key)
} else {
map.put(key, newSet)
}
return PersistentSetMultimap(newMap)
}
operator fun get(key: K): Set<V> {
return map[key] ?: emptySet()
}
}
@@ -0,0 +1,66 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve
import kotlinx.collections.immutable.*
class PersistentMultimap<K, V> private constructor(private val map: PersistentMap<K, PersistentList<V>>) {
constructor() : this(persistentMapOf())
fun put(key: K, value: V): PersistentMultimap<K, V> {
val collection = map[key] ?: persistentListOf()
val newSet = collection.add(value)
if (newSet === collection) return this
val newMap = map.put(key, newSet)
return PersistentMultimap(newMap)
}
fun remove(key: K, value: V): PersistentMultimap<K, V> {
val list = map.get(key) ?: return this
val newSet = list.remove(value)
if (list === newSet) return this
val newMap = if (newSet.isEmpty()) {
map.remove(key)
} else {
map.put(key, newSet)
}
return PersistentMultimap(newMap)
}
operator fun get(key: K): List<V> {
return map[key] ?: emptyList()
}
}
class PersistentSetMultimap<K, V> private constructor(private val map: PersistentMap<K, PersistentSet<V>>) {
constructor() : this(persistentMapOf())
fun put(key: K, value: V): PersistentSetMultimap<K, V> {
val set = map[key] ?: persistentSetOf()
val newSet = set.add(value)
if (newSet === set) return this
val newMap = map.put(key, newSet)
return PersistentSetMultimap(newMap)
}
fun remove(key: K, value: V): PersistentSetMultimap<K, V> {
val set = map.get(key) ?: return this
val newSet = set.remove(value)
if (set === newSet) return this
val newMap = if (newSet.isEmpty()) {
map.remove(key)
} else {
map.put(key, newSet)
}
return PersistentSetMultimap(newMap)
}
operator fun get(key: K): Set<V> {
return map[key] ?: emptySet()
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve
import kotlinx.collections.immutable.PersistentList
import org.jetbrains.kotlin.fir.FirCallResolver
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSymbolOwner
@@ -16,9 +17,13 @@ import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
import org.jetbrains.kotlin.fir.resolve.transformers.*
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.types.FirTypeRef
typealias FirLocalScopes = PersistentList<FirLocalScope>
interface SessionHolder {
val session: FirSession
}
@@ -26,6 +31,8 @@ interface SessionHolder {
interface BodyResolveComponents : SessionHolder {
val returnTypeCalculator: ReturnTypeCalculator
val implicitReceiverStack: ImplicitReceiverStack
val topLevelScopes: List<FirScope>
val localScopes: FirLocalScopes
val noExpectedType: FirTypeRef
val symbolProvider: FirSymbolProvider
val file: FirFile
@@ -32,9 +32,9 @@ class FirTowerResolver(
val typeCalculator: ReturnTypeCalculator,
val components: BodyResolveComponents,
resolutionStageRunner: ResolutionStageRunner,
private val topLevelScopes: List<FirScope>,
private val localScopes: List<FirLocalScope>
) {
private val localScopes: List<FirLocalScope> get() = components.localScopes.asReversed()
private val topLevelScopes: List<FirScope> get() = components.topLevelScopes.asReversed()
private val session: FirSession get() = components.session
private val collector = CandidateCollector(components, resolutionStageRunner)
@@ -5,10 +5,9 @@
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import kotlinx.collections.immutable.persistentListOf
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionStageRunner
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
@@ -50,6 +49,16 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
}
}
protected inline fun <T> withLocalScopeCleanup(crossinline l: () -> T): T {
return components.withLocalScopesCleanup(l)
}
protected fun addLocalScope(localScope: FirLocalScope?) {
if (localScope == null) return
components.addLocalScope(localScope)
}
@UseExperimental(PrivateForInline::class)
internal inline fun <T> withFullBodyResolve(crossinline l: () -> T): T {
if (!implicitTypeOnly) return l()
@@ -62,7 +71,7 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
}
protected inline val topLevelScopes: MutableList<FirScope> get() = components.topLevelScopes
protected inline val localScopes: MutableList<FirLocalScope> get() = components.localScopes
protected inline val localScopes: List<FirLocalScope> get() = components.localScopes
protected inline val noExpectedType: FirTypeRef get() = components.noExpectedType
@@ -94,8 +103,10 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
override val scopeSession: ScopeSession,
val transformer: FirBodyResolveTransformer
) : BodyResolveComponents {
val topLevelScopes: MutableList<FirScope> = mutableListOf()
val localScopes: MutableList<FirLocalScope> = mutableListOf()
override val topLevelScopes: MutableList<FirScope> = mutableListOf()
@set:PrivateForInline
override var localScopes: FirLocalScopes = persistentListOf()
override val noExpectedType: FirTypeRef = buildImplicitTypeRef()
@@ -117,12 +128,10 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
private val qualifiedResolver: FirQualifiedNameResolver = FirQualifiedNameResolver(this)
override val callResolver: FirCallResolver = FirCallResolver(
this,
topLevelScopes,
localScopes,
qualifiedResolver
)
val typeResolverTransformer = FirSpecificTypeResolverTransformer(
FirTypeResolveScopeForBodyResolve(topLevelScopes, implicitReceiverStack, localScopes), session
FirTypeResolveScopeForBodyResolve(this), session
)
override val callCompleter: FirCallCompleter = FirCallCompleter(transformer, this)
override val dataFlowAnalyzer: FirDataFlowAnalyzer<*> = FirDataFlowAnalyzer.createFirDataFlowAnalyzer(this)
@@ -160,6 +169,54 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
this.implicitReceiverStack = existedStack
}
}
@UseExperimental(PrivateForInline::class)
inline fun <R> withLocalScopes(localScopes: FirLocalScopes, l: () -> R): R {
val initialLocalScopes = this.localScopes
this.localScopes = localScopes
return try {
l()
} finally {
this.localScopes = initialLocalScopes
}
}
@UseExperimental(PrivateForInline::class)
inline fun <R> withLocalScopesCleanup(l: () -> R): R {
val initialLocalScopes = localScopes
return try {
l()
} finally {
localScopes = initialLocalScopes
}
}
@UseExperimental(PrivateForInline::class)
fun addLocalScope(localScope: FirLocalScope) {
localScopes = localScopes.add(localScope)
}
fun storeClass(klass: FirRegularClass) {
updateLastScope { storeClass(klass) }
}
fun storeFunction(function: FirSimpleFunction) {
updateLastScope { storeFunction(function) }
}
fun storeVariable(variable: FirVariable<*>) {
updateLastScope { storeVariable(variable) }
}
fun storeBackingField(property: FirProperty) {
updateLastScope { storeBackingField(property) }
}
@UseExperimental(PrivateForInline::class)
private inline fun updateLastScope(transform: FirLocalScope.() -> FirLocalScope) {
val lastScope = localScopes.lastOrNull() ?: return
localScopes = localScopes.set(localScopes.size - 1, lastScope.transform())
}
}
}
@@ -56,9 +56,9 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
}
whenExpression.annotations.forEach { it.accept(this, data) }
dataFlowAnalyzer.enterWhenExpression(whenExpression)
return withScopeCleanup(localScopes) with@{
return withLocalScopeCleanup with@{
if (whenExpression.subjectVariable != null) {
localScopes += FirLocalScope()
addLocalScope(FirLocalScope())
}
@Suppress("NAME_SHADOWING")
var whenExpression = whenExpression.transformSubject(transformer, ResolutionMode.ContextIndependent)
@@ -164,8 +164,8 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
override fun transformCatch(catch: FirCatch, data: ResolutionMode): CompositeTransformResult<FirCatch> {
dataFlowAnalyzer.enterCatchClause(catch)
catch.parameter.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent)
return withScopeCleanup(localScopes) {
localScopes += FirLocalScope()
return withLocalScopeCleanup {
addLocalScope(FirLocalScope())
catch.transformParameter(transformer, ResolutionMode.ContextIndependent)
catch.transformBlock(transformer, ResolutionMode.ContextDependent)
}.also { dataFlowAnalyzer.exitCatchClause(it) }.compose()
@@ -100,24 +100,22 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
}
dataFlowAnalyzer.enterProperty(property)
withFullBodyResolve {
withScopeCleanup(localScopes) {
withLocalScopeCleanup {
components.withContainer(property) {
if (property.delegate != null) {
localScopes.addIfNotNull(primaryConstructorParametersScope)
addLocalScope(primaryConstructorParametersScope)
transformPropertyWithDelegate(property)
} else {
withScopeCleanup(localScopes) {
localScopes.addIfNotNull(primaryConstructorParametersScope)
withLocalScopeCleanup {
addLocalScope(primaryConstructorParametersScope)
property.transformChildrenWithoutAccessors(returnTypeRef)
property.transformInitializer(integerLiteralTypeApproximator, null)
}
if (property.initializer != null) {
storeVariableReturnType(property)
}
withScopeCleanup(localScopes) {
localScopes.add(FirLocalScope().apply {
storeBackingField(property)
})
withLocalScopeCleanup {
addLocalScope(FirLocalScope().storeBackingField(property))
property.transformAccessors()
}
}
@@ -193,7 +191,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
}
variable.transformAccessors()
}
localScopes.lastOrNull()?.storeVariable(variable)
components.storeVariable(variable)
variable.replaceResolvePhase(transformerPhase)
dataFlowAnalyzer.exitLocalVariableDeclaration(variable)
return variable.compose()
@@ -292,7 +290,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
}
override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): CompositeTransformResult<FirStatement> {
localScopes.lastOrNull()?.storeClass(regularClass)
components.storeClass(regularClass)
return withScopeCleanup(topLevelScopes) {
prepareTypeParameterOwnerForBodyResolve(regularClass)
if (regularClass.symbol.classId.isLocal) {
@@ -307,8 +305,10 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
val result = withLabelAndReceiverType(regularClass.name, regularClass, type) {
val constructor = regularClass.declarations.firstOrNull() as? FirConstructor
if (constructor?.isPrimary == true) {
primaryConstructorParametersScope = FirLocalScope().apply {
constructor.valueParameters.forEach { this.storeVariable(it) }
primaryConstructorParametersScope = FirLocalScope().let {
var scope = it
constructor.valueParameters.forEach { scope = scope.storeVariable(it) }
scope
}
}
transformDeclaration(regularClass, data)
@@ -402,7 +402,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
returnTypeRef: FirTypeRef,
): CompositeTransformResult<F> {
if (function is FirSimpleFunction) {
localScopes.lastOrNull()?.storeFunction(function)
components.storeFunction(function)
}
@Suppress("UNCHECKED_CAST")
@@ -424,8 +424,8 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
}
override fun <F : FirFunction<F>> transformFunction(function: FirFunction<F>, data: ResolutionMode): CompositeTransformResult<FirStatement> {
return withScopeCleanup(localScopes) {
localScopes += FirLocalScope()
return withLocalScopeCleanup {
addLocalScope(FirLocalScope())
dataFlowAnalyzer.enterFunction(function)
@Suppress("UNCHECKED_CAST")
transformDeclaration(function, data).also {
@@ -448,9 +448,9 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
data: ResolutionMode
): CompositeTransformResult<FirDeclaration> {
if (implicitTypeOnly) return anonymousInitializer.compose()
return withScopeCleanup(localScopes) {
return withLocalScopeCleanup {
dataFlowAnalyzer.enterInitBlock(anonymousInitializer)
localScopes.addIfNotNull(primaryConstructorParametersScope)
addLocalScope(primaryConstructorParametersScope)
transformDeclaration(anonymousInitializer, ResolutionMode.ContextIndependent).also {
dataFlowAnalyzer.exitInitBlock(it.single as FirAnonymousInitializer)
}
@@ -458,7 +458,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
}
override fun transformValueParameter(valueParameter: FirValueParameter, data: ResolutionMode): CompositeTransformResult<FirStatement> {
localScopes.lastOrNull()?.storeVariable(valueParameter)
components.storeVariable(valueParameter)
if (valueParameter.returnTypeRef is FirImplicitTypeRef) {
valueParameter.replaceResolvePhase(transformerPhase)
return valueParameter.compose() // TODO
@@ -5,38 +5,52 @@
package org.jetbrains.kotlin.fir.scopes.impl
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentMapOf
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.NAME_FOR_BACKING_FIELD
import org.jetbrains.kotlin.fir.resolve.PersistentMultimap
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.Name
class FirLocalScope : FirScope() {
class FirLocalScope(
properties: PersistentMap<Name, FirVariableSymbol<*>>,
functions: PersistentMultimap<Name, FirFunctionSymbol<*>>,
classes: PersistentMap<Name, FirRegularClassSymbol>
) : FirScope() {
val properties: PersistentMap<Name, FirVariableSymbol<*>> = properties
val functions: PersistentMultimap<Name, FirFunctionSymbol<*>> = functions
val classes: PersistentMap<Name, FirRegularClassSymbol> = classes
val properties = mutableMapOf<Name, FirVariableSymbol<*>>()
val functions = mutableMapOf<Name, MutableList<FirFunctionSymbol<*>>>()
val classes = mutableMapOf<Name, FirRegularClassSymbol>()
constructor() : this(persistentMapOf(), PersistentMultimap(), persistentMapOf())
fun storeClass(klass: FirRegularClass) {
classes[klass.name] = klass.symbol
fun storeClass(klass: FirRegularClass): FirLocalScope {
return FirLocalScope(
properties, functions, classes.put(klass.name, klass.symbol)
)
}
fun storeFunction(function: FirSimpleFunction) {
functions.getOrPut(function.name) {
mutableListOf()
}.add(function.symbol as FirNamedFunctionSymbol)
fun storeFunction(function: FirSimpleFunction): FirLocalScope {
return FirLocalScope(
properties, functions.put(function.name, function.symbol as FirNamedFunctionSymbol), classes
)
}
fun storeVariable(variable: FirVariable<*>) {
properties[variable.name] = variable.symbol
fun storeVariable(variable: FirVariable<*>): FirLocalScope {
return FirLocalScope(
properties.put(variable.name, variable.symbol), functions, classes
)
}
fun storeBackingField(property: FirProperty) {
properties[NAME_FOR_BACKING_FIELD] = property.backingFieldSymbol
fun storeBackingField(property: FirProperty): FirLocalScope {
return FirLocalScope(
properties.put(NAME_FOR_BACKING_FIELD, property.backingFieldSymbol), functions, classes
)
}
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) {
for (function in functions[name].orEmpty()) {
for (function in functions[name]) {
processor(function)
}
}
@@ -5,18 +5,16 @@
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack
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
class FirTypeResolveScopeForBodyResolve(
private val topLevelScopes: List<FirScope>,
private val implicitReceiverStack: ImplicitReceiverStack,
private val localScopes: List<FirScope>
private val components: BodyResolveComponents
) : FirIterableScope() {
override val scopes: Iterable<FirScope>
get() = localScopes.asReversed() + implicitReceiverStack.receiversAsReversed().mapNotNull {
get() = components.localScopes.asReversed() + components.implicitReceiverStack.receiversAsReversed().mapNotNull {
(it as? ImplicitDispatchReceiverValue)?.implicitScope
} + topLevelScopes.asReversed()
} + components.topLevelScopes.asReversed()
}