From 4cb8faf666bee96f45d5c79f4bef40be30e28e1f Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 15 Apr 2019 16:47:35 +0300 Subject: [PATCH] FIR: uniquify scopes to avoid ambiguity on diamond inheritance --- .../kotlin/fir/backend/Fir2IrVisitor.kt | 5 +- .../kotlin/fir/java/JavaSymbolProvider.kt | 52 ++++++++++-- .../fir/java/declarations/FirJavaClass.kt | 29 ------- .../KotlinDeserializedJvmSymbolsProvider.kt | 9 ++- .../kotlin/fir/resolve/FirSymbolProvider.kt | 6 +- .../kotlin/fir/resolve/ScopeUtils.kt | 10 +-- .../kotlin/fir/resolve/SupertypeUtils.kt | 81 +++++++++++++------ .../kotlin/fir/resolve/calls/CallResolver.kt | 3 +- .../impl/FirCompositeSymbolProvider.kt | 9 ++- .../impl/FirDependenciesSymbolProviderImpl.kt | 13 +-- .../impl/FirLibrarySymbolProviderImpl.kt | 12 +-- .../fir/resolve/impl/FirProviderImpl.kt | 11 ++- .../transformers/FirBodyResolveTransformer.kt | 4 +- .../scopes/impl/FirAbstractImportingScope.kt | 11 +-- .../fir/scopes/impl/FirCompositeScope.kt | 10 ++- .../impl/FirTopLevelDeclaredMemberScope.kt | 3 +- .../java/AbstractFirTypeEnhancementTest.kt | 4 +- .../kotlin/fir/declarations/FirClass.kt | 2 - .../fir/IdeFirDependenciesSymbolProvider.kt | 3 +- .../fir/AbstractFirMultiModuleResolveTest.kt | 4 +- 20 files changed, 180 insertions(+), 101 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 6194e9792ac..5834061d10a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression import org.jetbrains.kotlin.fir.references.FirPropertyFromParameterCallableReference import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.scopes.ProcessorAction @@ -196,7 +197,7 @@ internal class Fir2IrVisitor( private fun IrClass.addFakeOverrides(klass: FirClass, processedFunctionNames: MutableList) { if (fakeOverrideMode == FakeOverrideMode.NONE) return val superTypesFunctionNames = klass.collectFunctionNamesFromSupertypes() - val useSiteScope = (klass as? FirRegularClass)?.buildUseSiteScope(session) ?: return + val useSiteScope = (klass as? FirRegularClass)?.buildUseSiteScope(session, ScopeSession()) ?: return for (name in superTypesFunctionNames) { if (name in processedFunctionNames) continue processedFunctionNames += name @@ -393,7 +394,7 @@ internal class Fir2IrVisitor( val classId = constructedClassSymbol.classId val provider = this@Fir2IrVisitor.session.service() var constructorSymbol: FirCallableSymbol? = null - provider.getClassUseSiteMemberScope(classId, this@Fir2IrVisitor.session)!!.processFunctionsByName( + provider.getClassUseSiteMemberScope(classId, this@Fir2IrVisitor.session, ScopeSession())!!.processFunctionsByName( classId.shortClassName ) { if (arguments.size <= ((it as FirFunctionSymbol).fir as FirFunction).valueParameters.size) { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt index ce49693502f..d503f0b0a6a 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -13,18 +13,20 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor import org.jetbrains.kotlin.fir.java.declarations.FirJavaField import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod -import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider -import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope -import org.jetbrains.kotlin.fir.resolve.constructType +import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope +import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteScope +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope +import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.types.ConeClassErrorType import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.load.java.JavaClassFinder import org.jetbrains.kotlin.load.java.JvmAnnotationNames @@ -52,9 +54,47 @@ class JavaSymbolProvider( return FirClassDeclaredMemberScope(classSymbol.fir) } - override fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession): FirScope? { + override fun getClassUseSiteMemberScope( + classId: ClassId, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): FirScope? { val symbol = this.getClassLikeSymbolByFqName(classId) ?: return null - return symbol.firUnsafe().buildUseSiteScope(useSiteSession) + val javaClass = symbol.firUnsafe() + return buildJavaEnhancementScope(useSiteSession, javaClass.symbol, scopeSession) + } + + private fun buildJavaEnhancementScope( + useSiteSession: FirSession, + symbol: FirClassSymbol, + scopeSession: ScopeSession + ): JavaClassEnhancementScope { + return scopeSession.getOrBuild(symbol, JAVA_ENHANCEMENT) { + JavaClassEnhancementScope(useSiteSession, buildJavaUseSiteScope(symbol.fir, useSiteSession, scopeSession)) + } + } + + private fun buildJavaUseSiteScope( + regularClass: FirRegularClass, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): JavaClassUseSiteScope { + return scopeSession.getOrBuild(regularClass.symbol, JAVA_USE_SITE) { + val superTypeEnhancementScope = FirCompositeScope(mutableListOf()) + val declaredScope = scopeSession.getOrBuild(regularClass.symbol, DECLARED) { FirClassDeclaredMemberScope(regularClass) } + lookupSuperTypes(regularClass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession) + .mapNotNullTo(superTypeEnhancementScope.scopes) { useSiteSuperType -> + if (useSiteSuperType is ConeClassErrorType) return@mapNotNullTo null + val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) + if (symbol is FirClassSymbol) { + // We need JavaClassEnhancementScope here to have already enhanced signatures from supertypes + buildJavaEnhancementScope(useSiteSession, symbol, scopeSession) + } else { + null + } + } + JavaClassUseSiteScope(regularClass, useSiteSession, superTypeEnhancementScope, declaredScope) + } } override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? { @@ -175,3 +215,5 @@ fun FqName.topLevelName() = asString().substringBefore(".") +private val JAVA_ENHANCEMENT = scopeSessionKey() +private val JAVA_USE_SITE = scopeSessionKey() \ No newline at end of file diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt index ec7c25de648..bd391c6cbae 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt @@ -13,15 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.impl.FirAbstractMemberDeclaration import org.jetbrains.kotlin.fir.declarations.impl.FirModifiableClass -import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope -import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteScope -import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes -import org.jetbrains.kotlin.fir.resolve.toSymbol -import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope -import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol -import org.jetbrains.kotlin.fir.types.ConeClassErrorType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name @@ -49,29 +41,8 @@ class FirJavaClass( override val superTypeRefs = mutableListOf() - override fun buildClassSpecificUseSiteScope(useSiteSession: FirSession): FirScope? { - return JavaClassEnhancementScope(useSiteSession, buildJavaUseSiteScope(this, useSiteSession)) - } - override val declarations = mutableListOf() - private fun buildJavaUseSiteScope(regularClass: FirRegularClass, useSiteSession: FirSession): JavaClassUseSiteScope { - val superTypeEnhancementScope = FirCompositeScope(mutableListOf()) - val declaredScope = FirClassDeclaredMemberScope(regularClass) - lookupSuperTypes(regularClass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession) - .mapNotNullTo(superTypeEnhancementScope.scopes) { useSiteSuperType -> - if (useSiteSuperType is ConeClassErrorType) return@mapNotNullTo null - val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) - if (symbol is FirClassSymbol) { - // We need JavaClassEnhancementScope here to have already enhanced signatures from supertypes - JavaClassEnhancementScope(useSiteSession, buildJavaUseSiteScope(symbol.fir, useSiteSession)) - } else { - null - } - } - return JavaClassUseSiteScope(regularClass, useSiteSession, superTypeEnhancementScope, declaredScope) - } - override fun replaceSupertypes(newSupertypes: List): FirRegularClass { superTypeRefs.clear() superTypeRefs.addAll(newSupertypes) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt index 1a8ceb4f0af..83de2506fe3 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt @@ -60,9 +60,14 @@ class KotlinDeserializedJvmSymbolsProvider( } } - override fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession): FirScope? { + override fun getClassUseSiteMemberScope( + classId: ClassId, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): FirScope? { val symbol = this.getClassLikeSymbolByFqName(classId) ?: return null - return symbol.firUnsafe().buildUseSiteScope(session) + + return symbol.firUnsafe().buildDefaultUseSiteScope(session, scopeSession) } override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt index 11dc37ae962..53ada571be5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt @@ -30,7 +30,11 @@ interface FirSymbolProvider { fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List fun getClassDeclaredMemberScope(classId: ClassId): FirScope? - fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession): FirScope? + fun getClassUseSiteMemberScope( + classId: ClassId, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): FirScope? fun getAllCallableNamesInPackage(fqName: FqName): Set = emptySet() fun getClassNamesInPackage(fqName: FqName): Set = emptySet() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt index 4aa5df4947f..851dfc5d0b8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt @@ -17,24 +17,24 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl -fun ConeKotlinType.scope(useSiteSession: FirSession): FirScope? { +fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? { return when (this) { is ConeKotlinErrorType -> null is ConeClassErrorType -> null - is ConeAbbreviatedType -> directExpansionType(useSiteSession)?.scope(useSiteSession) + is ConeAbbreviatedType -> directExpansionType(useSiteSession)?.scope(useSiteSession, scopeSession) is ConeClassLikeType -> { // For ConeClassLikeType they might be a type alias instead of a regular class // TODO: support that case and switch back to `firUnsafe` instead of `firSafeNullable` val fir = this.lookupTag.toSymbol(useSiteSession)?.firSafeNullable() ?: return null - fir.buildUseSiteScope(useSiteSession) + fir.buildUseSiteScope(useSiteSession, scopeSession) } is ConeTypeParameterType -> { // TODO: support LibraryTypeParameterSymbol or get rid of it val toSymbol = this.lookupTag.toSymbol(useSiteSession)?.takeIf { it is FirBasedSymbol<*> } ?: return null val fir = toSymbol.firUnsafe() - FirCompositeScope(fir.bounds.mapNotNullTo(mutableListOf()) { it.coneTypeUnsafe().scope(useSiteSession) }) + FirCompositeScope(fir.bounds.mapNotNullTo(mutableListOf()) { it.coneTypeUnsafe().scope(useSiteSession, scopeSession) }) } - is ConeFlexibleType -> lowerBound.scope(useSiteSession) + is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession) else -> error("Failed type ${this}") } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt index 75c8fdc932c..5d9c0f6c744 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt @@ -8,10 +8,12 @@ package org.jetbrains.kotlin.fir.resolve 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.classId import org.jetbrains.kotlin.fir.declarations.expandedConeType import org.jetbrains.kotlin.fir.declarations.superConeTypes import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.impl.* +import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol @@ -30,40 +32,67 @@ fun lookupSuperTypes( } } -fun FirRegularClass.buildUseSiteScope(useSiteSession: FirSession): FirScope { - return buildClassSpecificUseSiteScope(useSiteSession) ?: buildDefaultUseSiteScope(useSiteSession) +class ScopeSession { + private val scopes = mutableMapOf, FirScope>>() + fun getOrBuild(symbol: ConeClassifierSymbol, key: ScopeSessionKey, build: () -> T): T { + return scopes.getOrPut(symbol) { + mutableMapOf() + }.getOrPut(key) { + build() + } as T + } } -private fun FirRegularClass.buildDefaultUseSiteScope(useSiteSession: FirSession): FirScope { - val superTypeScope = FirCompositeScope(mutableListOf()) - val declaredScope = FirClassDeclaredMemberScope(this) - lookupSuperTypes(this, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession) - .mapNotNullTo(superTypeScope.scopes) { useSiteSuperType -> - if (useSiteSuperType is ConeClassErrorType) return@mapNotNullTo null - val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) - if (symbol is FirClassSymbol) { - val useSiteScope = symbol.fir.buildUseSiteScope(useSiteSession) - useSiteSuperType.buildSubstitutionScope(useSiteSession, useSiteScope, symbol.fir) ?: useSiteScope - } else { - null +abstract class ScopeSessionKey() + +inline fun scopeSessionKey(): ScopeSessionKey { + return object : ScopeSessionKey() {} +} + +val USE_SITE = scopeSessionKey() +val DECLARED = scopeSessionKey() + +data class SubstitutionScopeKey(val type: ConeClassLikeType) : ScopeSessionKey() {} + +fun FirRegularClass.buildUseSiteScope(useSiteSession: FirSession, builder: ScopeSession): FirScope { + val symbolProvider = useSiteSession.service() + return symbolProvider.getClassUseSiteMemberScope(this.classId, useSiteSession, builder)!! +} + +fun FirRegularClass.buildDefaultUseSiteScope(useSiteSession: FirSession, builder: ScopeSession): FirScope { + return builder.getOrBuild(symbol, USE_SITE) { + val superTypeScope = FirCompositeScope(mutableListOf()) + val declaredScope = builder.getOrBuild(this.symbol, DECLARED) { FirClassDeclaredMemberScope(this) } + lookupSuperTypes(this, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession) + .mapNotNullTo(superTypeScope.scopes) { useSiteSuperType -> + if (useSiteSuperType is ConeClassErrorType) return@mapNotNullTo null + val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) + if (symbol is FirClassSymbol) { + val useSiteScope = symbol.fir.buildUseSiteScope(useSiteSession, builder) + useSiteSuperType.wrapSubstitutionScopeIfNeed(useSiteSession, useSiteScope, symbol.fir, builder) + } else { + null + } } - } - return FirClassUseSiteScope(useSiteSession, superTypeScope, declaredScope) + FirClassUseSiteScope(useSiteSession, superTypeScope, declaredScope) + } } -private fun ConeClassLikeType.buildSubstitutionScope( +private fun ConeClassLikeType.wrapSubstitutionScopeIfNeed( session: FirSession, useSiteScope: FirScope, - regularClass: FirRegularClass -): FirClassSubstitutionScope? { - if (this.typeArguments.isEmpty()) return null + regularClass: FirRegularClass, + builder: ScopeSession +): FirScope { + if (this.typeArguments.isEmpty()) return useSiteScope + return builder.getOrBuild(regularClass.symbol, SubstitutionScopeKey(this)) { + @Suppress("UNCHECKED_CAST") + val substitution = regularClass.typeParameters.zip(this.typeArguments) { typeParameter, typeArgument -> + typeParameter.symbol to (typeArgument as? ConeTypedProjection)?.type + }.filter { (_, type) -> type != null }.toMap() as Map - @Suppress("UNCHECKED_CAST") - val substitution = regularClass.typeParameters.zip(this.typeArguments) { typeParameter, typeArgument -> - typeParameter.symbol to (typeArgument as? ConeTypedProjection)?.type - }.filter { (_, type) -> type != null }.toMap() as Map - - return FirClassSubstitutionScope(session, useSiteScope, substitution) + FirClassSubstitutionScope(session, useSiteScope, substitution) + } } private tailrec fun ConeClassLikeType.computePartialExpansion(useSiteSession: FirSession): ConeClassLikeType? { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt index 95815415ce3..0fe7c56f4a5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.renderWithType import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor @@ -143,7 +144,7 @@ class MemberScopeTowerLevel( output: TowerScopeLevel.TowerScopeLevelProcessor, processScopeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction ): ProcessorAction { - val scope = dispatchReceiver.type.scope(session) ?: return ProcessorAction.NEXT + val scope = dispatchReceiver.type.scope(session, ScopeSession()) ?: return ProcessorAction.NEXT if (scope.processScopeMembers { output.consumeCandidate(it, dispatchReceiver) }.stop()) return ProcessorAction.STOP val withSynthetic = FirSyntheticPropertiesScope(session, scope, ReturnTypeCalculatorWithJump(session)) return withSynthetic.processScopeMembers { output.consumeCandidate(it, dispatchReceiver) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirCompositeSymbolProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirCompositeSymbolProvider.kt index 9be4a1fb165..738dc3fb5a3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirCompositeSymbolProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirCompositeSymbolProvider.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.impl import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol @@ -16,8 +17,12 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult class FirCompositeSymbolProvider(val providers: List) : FirSymbolProvider { - override fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession): FirScope? { - return providers.firstNotNullResult { it.getClassUseSiteMemberScope(classId, useSiteSession) } + override fun getClassUseSiteMemberScope( + classId: ClassId, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): FirScope? { + return providers.firstNotNullResult { it.getClassUseSiteMemberScope(classId, useSiteSession, scopeSession) } } override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirDependenciesSymbolProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirDependenciesSymbolProviderImpl.kt index 24b769873a8..0d14217be2f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirDependenciesSymbolProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirDependenciesSymbolProviderImpl.kt @@ -6,12 +6,10 @@ package org.jetbrains.kotlin.fir.resolve.impl import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.dependenciesWithoutSelf import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider -import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope -import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.symbols.CallableId @@ -50,9 +48,12 @@ class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSy } } - override fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession): FirScope? { - val symbol = this.getClassLikeSymbolByFqName(classId) ?: return null - return symbol.firUnsafe().buildUseSiteScope(useSiteSession) + override fun getClassUseSiteMemberScope( + classId: ClassId, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): FirScope? { + return dependencyProviders.firstNotNullResult { it.getClassUseSiteMemberScope(classId, useSiteSession, scopeSession) } } override fun getPackage(fqName: FqName): FqName? { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirLibrarySymbolProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirLibrarySymbolProviderImpl.kt index f5f718f0ec3..5a930bd32a8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirLibrarySymbolProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirLibrarySymbolProviderImpl.kt @@ -18,9 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol -import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider -import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope -import org.jetbrains.kotlin.fir.resolve.getOrPut +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope @@ -106,9 +104,13 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider } } - override fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession): FirScope? { + override fun getClassUseSiteMemberScope( + classId: ClassId, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): FirScope? { val symbol = this.getClassLikeSymbolByFqName(classId) ?: return null - return symbol.firUnsafe().buildUseSiteScope(useSiteSession) + return symbol.firUnsafe().buildDefaultUseSiteScope(useSiteSession, scopeSession) } override fun getPackage(fqName: FqName): FqName? { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirProviderImpl.kt index 18b6beed5a9..573aecd078e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirProviderImpl.kt @@ -10,7 +10,8 @@ import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.FirProvider -import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.buildDefaultUseSiteScope import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope @@ -193,9 +194,13 @@ class FirProviderImpl(val session: FirSession) : FirProvider { } } - override fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession): FirScope? { + override fun getClassUseSiteMemberScope( + classId: ClassId, + useSiteSession: FirSession, + scopeSession: ScopeSession + ): FirScope? { val symbol = this.getClassLikeSymbolByFqName(classId) ?: return null - return symbol.firUnsafe().buildUseSiteScope(useSiteSession) + return symbol.firUnsafe().buildDefaultUseSiteScope(useSiteSession, scopeSession) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt index dd8fa7a0f98..1f7fc682363 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt @@ -86,7 +86,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult { return withScopeCleanup(scopes) { val type = regularClass.defaultType() - scopes.addIfNotNull(type.scope(session)) + scopes.addIfNotNull(type.scope(session, ScopeSession())) withLabel(regularClass.name, type) { super.transformRegularClass(regularClass, data) } @@ -484,7 +484,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn fun transform(): CompositeTransformResult { localScopes.lastOrNull()?.storeDeclaration(namedFunction) return withScopeCleanup(scopes) { - scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe()?.scope(session)) + scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe()?.scope(session, ScopeSession())) val result = super.transformNamedFunction(namedFunction, namedFunction.returnTypeRef).single as FirNamedFunction diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractImportingScope.kt index 5eb273056f1..e6972b512d7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractImportingScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractImportingScope.kt @@ -7,8 +7,9 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirResolvedImport +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope import org.jetbrains.kotlin.fir.resolve.calls.TowerScopeLevel -import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol @@ -21,7 +22,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.cast abstract class FirAbstractImportingScope(session: FirSession, lookupInFir: Boolean) : FirAbstractProviderBasedScope(session, lookupInFir) { - protected val scopeCache = mutableMapOf() + protected val scopeCache = ScopeSession() fun processCallables( import: FirResolvedImport, @@ -34,9 +35,9 @@ abstract class FirAbstractImportingScope(session: FirSession, lookupInFir: Boole val classId = import.resolvedClassId if (classId != null) { - val scope = scopeCache.getOrPut(classId) { - provider.getClassUseSiteMemberScope(classId, session) ?: error("No scope for $classId") - } + val scope = + provider.getClassUseSiteMemberScope(classId, session, scopeCache) ?: error("No scope for $classId") + val action = when (token) { TowerScopeLevel.Token.Functions -> scope.processFunctionsByName( callableId.callableName, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirCompositeScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirCompositeScope.kt index 4d692ba2a40..2fc1123a788 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirCompositeScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirCompositeScope.kt @@ -40,9 +40,17 @@ class FirCompositeScope( name: Name, noinline processor: (T) -> ProcessorAction ): ProcessorAction { + val unique = mutableSetOf() val scopes = if (reversedPriority) scopes.asReversed() else scopes for (scope in scopes) { - if (!scope.process(name, processor)) { + if (!scope.process(name) { + if (unique.add(it)) { + processor(it) + } else { + NEXT + } + } + ) { return STOP } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTopLevelDeclaredMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTopLevelDeclaredMemberScope.kt index f449b3f15d7..e034d2a4c96 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTopLevelDeclaredMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTopLevelDeclaredMemberScope.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT @@ -30,7 +31,7 @@ class FirTopLevelDeclaredMemberScope( if (matchedClass != null && matchedClass is FirClassSymbol) { // TODO: why don't we use declared member scope at this point? - if (matchedClass.fir.buildUseSiteScope(session).processFunctionsByName(name, processor) == STOP) { + if (matchedClass.fir.buildUseSiteScope(session, ScopeSession()).processFunctionsByName(name, processor) == STOP) { return STOP } } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt index 5b2c3c6d488..e5a9fcc8255 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt @@ -22,12 +22,14 @@ import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.createSession import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.classId import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor import org.jetbrains.kotlin.fir.java.declarations.FirJavaField import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope @@ -170,7 +172,7 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() { val processedJavaClasses = mutableSetOf() for (javaClass in javaProvider.getJavaTopLevelClasses().sortedBy { it.name }) { if (javaClass !is FirJavaClass || javaClass in processedJavaClasses) continue - val enhancementScope = javaClass.buildClassSpecificUseSiteScope(session).let { + val enhancementScope = javaProvider.getClassUseSiteMemberScope(javaClass.classId, session, ScopeSession()).let { when (it) { is FirCompositeScope -> it.scopes.filterIsInstance().first() is JavaClassEnhancementScope -> it diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirClass.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirClass.kt index f09c785bd8c..b3cc2334755 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirClass.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirClass.kt @@ -21,8 +21,6 @@ interface FirClass : FirDeclarationContainer, FirStatement, FirAnnotationContain val classKind: ClassKind - fun buildClassSpecificUseSiteScope(useSiteSession: FirSession): FirScope? = null - override fun accept(visitor: FirVisitor, data: D): R = visitor.visitClass(this, data) diff --git a/idea/src/org/jetbrains/kotlin/idea/fir/IdeFirDependenciesSymbolProvider.kt b/idea/src/org/jetbrains/kotlin/idea/fir/IdeFirDependenciesSymbolProvider.kt index a9c87fb6e27..63a9cc10b34 100644 --- a/idea/src/org/jetbrains/kotlin/idea/fir/IdeFirDependenciesSymbolProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/fir/IdeFirDependenciesSymbolProvider.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider import org.jetbrains.kotlin.fir.resolve.FirProvider +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.service @@ -64,7 +65,7 @@ class IdeFirDependenciesSymbolProvider( } } - override fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession): FirScope? { + override fun getClassUseSiteMemberScope(classId: ClassId, useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? { TODO("not implemented") } diff --git a/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt b/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt index e77ba0ab4ee..3f12b6dfe5e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.classId import org.jetbrains.kotlin.fir.dependenciesWithoutSelf import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession import org.jetbrains.kotlin.fir.java.FirLibrarySession @@ -24,6 +25,7 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope import org.jetbrains.kotlin.fir.resolve.FirProvider import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer @@ -135,7 +137,7 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() { val javaProvider = symbolProvider.providers.filterIsInstance().first() for (javaClass in javaProvider.getJavaTopLevelClasses().sortedBy { it.name }) { if (javaClass !is FirJavaClass || javaClass in processedJavaClasses) continue - val enhancementScope = javaClass.buildClassSpecificUseSiteScope(session).let { + val enhancementScope = javaProvider.getClassUseSiteMemberScope(javaClass.classId, session, ScopeSession()).let { when (it) { is FirCompositeScope -> it.scopes.filterIsInstance().first() is JavaClassEnhancementScope -> it