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 62ded07fd9e..1d806565237 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 @@ -21,7 +21,7 @@ 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.scopes.impl.FirSuperTypeScope import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol @@ -86,20 +86,21 @@ class JavaSymbolProvider( 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 + val superTypeEnhancementScopes = + lookupSuperTypes(regularClass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession) + .mapNotNull { useSiteSuperType -> + if (useSiteSuperType is ConeClassErrorType) return@mapNotNull null + val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) + if (symbol is FirClassSymbol) { + // We need JavaClassEnhancementScope here to have already enhanced signatures from supertypes + val scope = buildJavaEnhancementScope(useSiteSession, symbol, scopeSession) + useSiteSuperType.wrapSubstitutionScopeIfNeed(useSiteSession, scope, scopeSession) + } else { + null + } } - } - JavaClassUseSiteScope(regularClass, useSiteSession, superTypeEnhancementScope, declaredScope) + JavaClassUseSiteScope(regularClass, useSiteSession, FirSuperTypeScope(session, superTypeEnhancementScopes), declaredScope) } } 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 9cff9ef75e8..71c07bb3c49 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 @@ -45,7 +45,7 @@ fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession) } } -private fun ConeClassLikeType.wrapSubstitutionScopeIfNeed( +fun ConeClassLikeType.wrapSubstitutionScopeIfNeed( session: FirSession, useSiteScope: FirScope, builder: ScopeSession 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 37ca1486136..eb021735c94 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 @@ -65,11 +65,11 @@ fun FirTypeAlias.buildUseSiteScope(useSiteSession: FirSession, builder: ScopeSes 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 scopes = lookupSuperTypes(this, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession) + .mapNotNull { useSiteSuperType -> + if (useSiteSuperType is ConeClassErrorType) return@mapNotNull null val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) if (symbol is FirClassSymbol) { val useSiteScope = symbol.fir.buildUseSiteScope(useSiteSession, builder) @@ -78,7 +78,7 @@ fun FirRegularClass.buildDefaultUseSiteScope(useSiteSession: FirSession, builder null } } - FirClassUseSiteScope(useSiteSession, superTypeScope, declaredScope) + FirClassUseSiteScope(useSiteSession, FirSuperTypeScope(useSiteSession, scopes), declaredScope) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirOverrideScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirOverrideScope.kt new file mode 100644 index 00000000000..1163d172552 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirOverrideScope.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.scopes.impl + +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol +import org.jetbrains.kotlin.fir.typeContext +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.ConeTypeContext +import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker +import org.jetbrains.kotlin.utils.addToStdlib.cast + +abstract class AbstractFirOverrideScope(val session: FirSession) : FirScope { + //base symbol as key + val overrides = mutableMapOf() + + val context: ConeTypeContext = session.typeContext + + private fun isEqualTypes(a: ConeKotlinType, b: ConeKotlinType) = AbstractStrictEqualityTypeChecker.strictEqualTypes(context, a, b) + + private fun isEqualTypes(a: FirTypeRef, b: FirTypeRef) = + isEqualTypes(a.cast().type, b.cast().type) + + private fun isOverriddenFunCheck(member: FirNamedFunction, self: FirNamedFunction): Boolean { + return member.valueParameters.size == self.valueParameters.size && + member.valueParameters.zip(self.valueParameters).all { (memberParam, selfParam) -> + isEqualTypes(memberParam.returnTypeRef, selfParam.returnTypeRef) + } + } + + protected fun ConeCallableSymbol.isOverridden(seen: Set): ConeCallableSymbol? { + if (overrides.containsKey(this)) return overrides[this] + + fun sameReceivers(memberTypeRef: FirTypeRef?, selfTypeRef: FirTypeRef?): Boolean { + return when { + memberTypeRef != null && selfTypeRef != null -> isEqualTypes(memberTypeRef, selfTypeRef) + else -> memberTypeRef == null && selfTypeRef == null + } + } + + fun similarFunctionsOrBothProperties(declaration: FirCallableDeclaration, self: FirCallableDeclaration): Boolean { + return when (declaration) { + is FirNamedFunction -> self is FirNamedFunction && isOverriddenFunCheck(declaration, self) + is FirConstructor -> false + is FirProperty -> self is FirProperty + else -> error("Unknown fir callable type: $declaration, $self") + } + } + + val self = (this as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration + val overriding = seen.firstOrNull { + val member = (it as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration + self.modality != Modality.FINAL + && sameReceivers(member.receiverTypeRef, self.receiverTypeRef) + && similarFunctionsOrBothProperties(member, self) + } // TODO: two or more overrides for one fun? + overrides[this] = overriding + return overriding + } + +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassUseSiteScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassUseSiteScope.kt index f520bf7ae2c..d9cd6f9b551 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassUseSiteScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassUseSiteScope.kt @@ -5,74 +5,19 @@ package org.jetbrains.kotlin.fir.scopes.impl -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT import org.jetbrains.kotlin.fir.scopes.ProcessorAction.STOP import org.jetbrains.kotlin.fir.symbols.* -import org.jetbrains.kotlin.fir.typeContext -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.ConeTypeContext -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker -import org.jetbrains.kotlin.utils.addToStdlib.cast class FirClassUseSiteScope( session: FirSession, private val superTypesScope: FirScope, private val declaredMemberScope: FirScope -) : FirAbstractProviderBasedScope(session, lookupInFir = true) { - //base symbol as key - val overrides = mutableMapOf() - - val context: ConeTypeContext = session.typeContext - - private fun isEqualTypes(a: ConeKotlinType, b: ConeKotlinType) = AbstractStrictEqualityTypeChecker.strictEqualTypes(context, a, b) - - private fun isEqualTypes(a: FirTypeRef, b: FirTypeRef) = - isEqualTypes(a.cast().type, b.cast().type) - - private fun isOverriddenFunCheck(member: FirNamedFunction, self: FirNamedFunction): Boolean { - return member.valueParameters.size == self.valueParameters.size && - member.valueParameters.zip(self.valueParameters).all { (memberParam, selfParam) -> - isEqualTypes(memberParam.returnTypeRef, selfParam.returnTypeRef) - } - } - - private fun ConeCallableSymbol.isOverridden(seen: Set): ConeCallableSymbol? { - if (overrides.containsKey(this)) return overrides[this] - - fun sameReceivers(memberTypeRef: FirTypeRef?, selfTypeRef: FirTypeRef?): Boolean { - return when { - memberTypeRef != null && selfTypeRef != null -> isEqualTypes(memberTypeRef, selfTypeRef) - else -> memberTypeRef == null && selfTypeRef == null - } - } - - fun similarFunctionsOrBothProperties(declaration: FirCallableDeclaration, self: FirCallableDeclaration): Boolean { - return when (declaration) { - is FirNamedFunction -> self is FirNamedFunction && isOverriddenFunCheck(declaration, self) - is FirConstructor -> false - is FirProperty -> self is FirProperty - else -> error("Unknown fir callable type: $declaration, $self") - } - } - - val self = (this as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration - val overriding = seen.firstOrNull { - val member = (it as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration - self.modality != Modality.FINAL - && sameReceivers(member.receiverTypeRef, self.receiverTypeRef) - && similarFunctionsOrBothProperties(member, self) - } // TODO: two or more overrides for one fun? - overrides[this] = overriding - return overriding - } +) : AbstractFirOverrideScope(session) { override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction { val seen = mutableSetOf() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSuperTypeScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSuperTypeScope.kt new file mode 100644 index 00000000000..463a1d55eb6 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSuperTypeScope.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.scopes.impl + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol +import org.jetbrains.kotlin.fir.symbols.ConeFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.ConeVariableSymbol +import org.jetbrains.kotlin.name.Name + +class FirSuperTypeScope( + session: FirSession, + val scopes: List +) : AbstractFirOverrideScope(session) { + + override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction { + val accepted = mutableSetOf() + val pending = mutableSetOf() + for (scope in scopes) { + if (scope.processFunctionsByName(name) { + + if (it !in accepted && it.isOverridden(accepted) == null) { + pending += it + processor(it) + } else { + ProcessorAction.NEXT + } + }.stop() + ) { + return ProcessorAction.STOP + } + accepted += pending + pending.clear() + } + return super.processFunctionsByName(name, processor) + } + + override fun processPropertiesByName(name: Name, processor: (ConeVariableSymbol) -> ProcessorAction): ProcessorAction { + val accepted = mutableSetOf() + val pending = mutableSetOf() + for (scope in scopes) { + if (scope.processPropertiesByName(name) { + if (it !in accepted && it.isOverridden(accepted) == null) { + pending += it + processor(it) + } else { + ProcessorAction.NEXT + } + }.stop() + ) { + return ProcessorAction.STOP + } + accepted += pending + pending.clear() + } + return super.processPropertiesByName(name, processor) + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.txt b/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.txt index 045e9a11769..ea126c1c809 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.txt @@ -1,5 +1,5 @@ FILE: typeAliasDeserialization.kt public final fun main(): R|kotlin/Unit| { lval a: R|java/util/LinkedHashSet| = R|java/util/LinkedHashSet.LinkedHashSet|() - R|/a|.#(String()) + R|/a|.R|FakeOverride|(String()) } diff --git a/compiler/testData/loadJava/compiledJava/kotlinSignature/propagation/return/SubclassOfMapEntry.fir.txt b/compiler/testData/loadJava/compiledJava/kotlinSignature/propagation/return/SubclassOfMapEntry.fir.txt index 6a4f69872a5..f1a5e80f46f 100644 --- a/compiler/testData/loadJava/compiledJava/kotlinSignature/propagation/return/SubclassOfMapEntry.fir.txt +++ b/compiler/testData/loadJava/compiledJava/kotlinSignature/propagation/return/SubclassOfMapEntry.fir.txt @@ -1,6 +1,4 @@ public abstract interface SubclassOfMapEntry : R|java/util/Map.Entry| { public abstract operator fun setValue(value: R|ft|!): R|ft|! - public abstract operator fun setValue(: R|ft|!): R|ft|! - }