diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt index 7068526a1cc..d5423910b42 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt @@ -6,14 +6,12 @@ package org.jetbrains.kotlin.fir.java.scopes import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.* import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl -import org.jetbrains.kotlin.fir.impl.FirAbstractAnnotatedElement import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.declarations.* import org.jetbrains.kotlin.fir.java.enhancement.* @@ -352,7 +350,7 @@ class JavaClassEnhancementScope( val backMap = overrideBindCache.getOrPut(this.name) { useSiteScope.bindOverrides(this.name) useSiteScope - .overriddenByBase + .overrideByBase .toList() .groupBy({ (_, key) -> key }, { (value) -> value }) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteScope.kt index 591ab9b3030..dcb8b8adabc 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteScope.kt @@ -16,30 +16,25 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction.* +import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteScope import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope import org.jetbrains.kotlin.fir.symbols.* import org.jetbrains.kotlin.fir.symbols.impl.* -import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.name.Name class JavaClassUseSiteScope( klass: FirRegularClass, - private val session: FirSession, - private val superTypesScope: FirSuperTypeScope, - private val declaredMemberScope: FirScope -) : FirScope() { + session: FirSession, + superTypesScope: FirSuperTypeScope, + declaredMemberScope: FirScope +) : AbstractFirUseSiteScope(session, superTypesScope, declaredMemberScope) { internal val symbol = klass.symbol private val javaTypeParameterStack: JavaTypeParameterStack = if (klass is FirJavaClass) klass.javaTypeParameterStack else JavaTypeParameterStack.EMPTY - //base symbol as key, overridden as value - internal val overriddenByBase = mutableMapOf, FirCallableSymbol<*>?>() - - private val context: ConeTypeContext = session.typeContext - private fun isEqualTypes(a: ConeKotlinType, b: ConeKotlinType, substitutor: ConeSubstitutor): Boolean { if (a is ConeFlexibleType) return isEqualTypes(a.lowerBound, b, substitutor) if (b is ConeFlexibleType) return isEqualTypes(a, b.lowerBound, substitutor) @@ -58,18 +53,19 @@ class JavaClassUseSiteScope( substitutor ) - private fun isOverriddenFunCheck(overriddenInJava: FirSimpleFunction, base: FirSimpleFunction): Boolean { - val receiverTypeRef = base.receiverTypeRef - val baseParameterTypes = listOfNotNull(receiverTypeRef) + base.valueParameters.map { it.returnTypeRef } + override fun isOverriddenFunCheck(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean { + // NB: overrideCandidate is from Java and has no receiver + val receiverTypeRef = baseDeclaration.receiverTypeRef + val baseParameterTypes = listOfNotNull(receiverTypeRef) + baseDeclaration.valueParameters.map { it.returnTypeRef } - if (overriddenInJava.valueParameters.size != baseParameterTypes.size) return false - if (overriddenInJava.typeParameters.size != base.typeParameters.size) return false + if (overrideCandidate.valueParameters.size != baseParameterTypes.size) return false + if (overrideCandidate.typeParameters.size != baseDeclaration.typeParameters.size) return false - val types = base.typeParameters.map { + val types = baseDeclaration.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) } - val substitution = substitutorByMap(overriddenInJava.typeParameters.map { it.symbol }.zip(types).toMap()) - if (!overriddenInJava.typeParameters.zip(base.typeParameters).all { (a, b) -> + val substitution = substitutorByMap(overrideCandidate.typeParameters.map { it.symbol }.zip(types).toMap()) + if (!overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).all { (a, b) -> a.bounds.size == b.bounds.size && a.bounds.zip(b.bounds).all { (aBound, bBound) -> isEqualTypes(aBound, bBound, substitution) } @@ -77,29 +73,33 @@ class JavaClassUseSiteScope( ) return false - return overriddenInJava.valueParameters.zip(baseParameterTypes).all { (paramFromJava, baseType) -> + return overrideCandidate.valueParameters.zip(baseParameterTypes).all { (paramFromJava, baseType) -> isEqualTypes(paramFromJava.returnTypeRef, baseType, substitution) } } - private fun isOverriddenPropertyCheck(overriddenInJava: FirSimpleFunction, base: FirProperty): Boolean { - val receiverTypeRef = base.receiverTypeRef - if (receiverTypeRef == null) { - // TODO: setters - return overriddenInJava.valueParameters.isEmpty() - } else { - if (overriddenInJava.valueParameters.size != 1) return false - return isEqualTypes(receiverTypeRef, overriddenInJava.valueParameters.single().returnTypeRef, ConeSubstitutor.Empty) - } - } - - private fun isOverriddenPropertyCheck(overriddenInKotlin: FirProperty, base: FirProperty): Boolean { - val receiverTypeRef = base.receiverTypeRef - val overriddenReceiverTypeRef = overriddenInKotlin.receiverTypeRef - return when { - receiverTypeRef == null -> overriddenReceiverTypeRef == null - overriddenReceiverTypeRef == null -> false - else -> isEqualTypes(receiverTypeRef, overriddenReceiverTypeRef, ConeSubstitutor.Empty) + override fun isOverriddenPropertyCheck(overrideCandidate: FirCallableMemberDeclaration<*>, baseDeclaration: FirProperty): Boolean { + if (baseDeclaration.modality == Modality.FINAL) return false + val receiverTypeRef = baseDeclaration.receiverTypeRef + return when (overrideCandidate) { + is FirSimpleFunction -> { + if (receiverTypeRef == null) { + // TODO: setters + return overrideCandidate.valueParameters.isEmpty() + } else { + if (overrideCandidate.valueParameters.size != 1) return false + return isEqualTypes(receiverTypeRef, overrideCandidate.valueParameters.single().returnTypeRef, ConeSubstitutor.Empty) + } + } + is FirProperty -> { + val overrideReceiverTypeRef = overrideCandidate.receiverTypeRef + return when { + receiverTypeRef == null -> overrideReceiverTypeRef == null + overrideReceiverTypeRef == null -> false + else -> isEqualTypes(receiverTypeRef, overrideReceiverTypeRef, ConeSubstitutor.Empty) + } + } + else -> false } } @@ -117,70 +117,6 @@ class JavaClassUseSiteScope( } } - private fun FirCallableSymbol<*>.getOverridden(candidates: Set>): FirCallableSymbol<*>? { - if (overriddenByBase.containsKey(this)) return overriddenByBase[this] - - val overriding = when (this) { - is FirNamedFunctionSymbol -> { - val self = this.fir - candidates.firstOrNull { - val overridden = (it as? FirNamedFunctionSymbol)?.fir - overridden != null && self.modality != Modality.FINAL && isOverriddenFunCheck(overridden, self) - } - } - is FirConstructorSymbol, is FirFieldSymbol -> { - null - } - is FirPropertySymbol -> { - val self = fir - candidates.firstOrNull { - when (it) { - is FirNamedFunctionSymbol -> { - val overridden = it.fir - self.modality != Modality.FINAL && isOverriddenPropertyCheck(overridden, self) - } - is FirPropertySymbol -> { - val overridden = it.fir - self.modality != Modality.FINAL && isOverriddenPropertyCheck(overridden, self) - } - else -> false - } - - } - } - is FirAccessorSymbol -> { - val self = fir - candidates.firstOrNull { - val overridden = (it as? FirNamedFunctionSymbol)?.fir - overridden != null && self.modality != Modality.FINAL && isOverriddenFunCheck(overridden, self) - } - } - else -> error("Unexpected callable symbol: $this") - } - // TODO: two or more overrides for one fun? - overriddenByBase[this] = overriding - return overriding - } - - override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction { - val overrideCandidates = mutableSetOf>() - if (!declaredMemberScope.processFunctionsByName(name) { - overrideCandidates += it - processor(it) - } - ) return STOP - - return superTypesScope.processFunctionsByName(name) { - - val overriddenBy = it.getOverridden(overrideCandidates) - if (overriddenBy == null) { - processor(it) - } else { - NEXT - } - } - } - private fun processAccessorFunctionsAndPropertiesByName( propertyName: Name, accessorName: Name, 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 index 0fb300ceaac..b7066783c9b 100644 --- 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 @@ -20,10 +20,10 @@ 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, FirCallableSymbol<*>?>() + //base symbol as key, overridden as value + val overrideByBase = mutableMapOf, FirCallableSymbol<*>?>() - val context: ConeTypeContext = session.typeContext + protected val context: ConeTypeContext = session.typeContext private fun isEqualTypes(a: ConeKotlinType, b: ConeKotlinType, substitution: ConeSubstitutor) = AbstractStrictEqualityTypeChecker.strictEqualTypes(context, substitution.substituteOrSelf(a), substitution.substituteOrSelf(b)) @@ -31,26 +31,35 @@ abstract class AbstractFirOverrideScope(val session: FirSession) : FirScope() { private fun isEqualTypes(a: FirTypeRef, b: FirTypeRef, substitution: ConeSubstitutor) = isEqualTypes(a.cast().type, b.cast().type, substitution) - private fun isOverriddenFunCheck(member: FirSimpleFunction, self: FirSimpleFunction): Boolean { - if (member.valueParameters.size != self.valueParameters.size) return false - if (member.typeParameters.size != self.typeParameters.size) return false + protected open fun isOverriddenFunCheck(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean { + if (overrideCandidate.valueParameters.size != baseDeclaration.valueParameters.size) return false + if (overrideCandidate.typeParameters.size != baseDeclaration.typeParameters.size) return false - val types = self.typeParameters.map { + val types = baseDeclaration.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) } - val substitution = substitutorByMap(member.typeParameters.map { it.symbol }.zip(types).toMap()) - if (!member.typeParameters.zip(self.typeParameters).all { (a, b) -> + val substitution = substitutorByMap(overrideCandidate.typeParameters.map { it.symbol }.zip(types).toMap()) + if (!overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).all { (a, b) -> a.bounds.size == b.bounds.size && a.bounds.zip(b.bounds).all { (aBound, bBound) -> isEqualTypes(aBound, bBound, substitution) } } ) return false - if (!sameReceivers(member.receiverTypeRef, self.receiverTypeRef, substitution)) return false + if (!sameReceivers(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, substitution)) return false - return member.valueParameters.zip(self.valueParameters).all { (memberParam, selfParam) -> + return overrideCandidate.valueParameters.zip(baseDeclaration.valueParameters).all { (memberParam, selfParam) -> isEqualTypes(memberParam.returnTypeRef, selfParam.returnTypeRef, substitution) } } + protected open fun isOverriddenPropertyCheck( + overrideCandidate: FirCallableMemberDeclaration<*>, // NB: in Java it can be a function which overrides accessor + baseDeclaration: FirProperty + ): Boolean { + // TODO: substitutor + return overrideCandidate is FirProperty && + sameReceivers(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, ConeSubstitutor.Empty) + } + private fun sameReceivers(memberTypeRef: FirTypeRef?, selfTypeRef: FirTypeRef?, substitution: ConeSubstitutor): Boolean { return when { memberTypeRef != null && selfTypeRef != null -> isEqualTypes(memberTypeRef, selfTypeRef, substitution) @@ -58,31 +67,34 @@ abstract class AbstractFirOverrideScope(val session: FirSession) : FirScope() { } } - protected fun FirCallableSymbol<*>.isOverridden(seen: Set>): FirCallableSymbol<*>? { - if (overrides.containsKey(this)) return overrides[this] - - fun similarFunctionsOrBothProperties(declaration: FirCallableDeclaration<*>, self: FirCallableDeclaration<*>): Boolean { - return when (declaration) { - is FirSimpleFunction -> self is FirSimpleFunction && isOverriddenFunCheck(declaration, self) - is FirConstructor -> false - is FirProperty -> self is FirProperty && sameReceivers( - declaration.receiverTypeRef, - self.receiverTypeRef, - ConeSubstitutor.Empty // TODO - ) - is FirField -> false - else -> error("Unknown fir callable type: $declaration, $self") + private fun similarFunctionsOrBothProperties( + overrideCandidate: FirCallableMemberDeclaration<*>, + baseDeclaration: FirCallableMemberDeclaration<*> + ): Boolean { + return when (overrideCandidate) { + is FirSimpleFunction -> when (baseDeclaration) { + is FirSimpleFunction -> isOverriddenFunCheck(overrideCandidate, baseDeclaration) + is FirProperty -> isOverriddenPropertyCheck(overrideCandidate, baseDeclaration) + else -> false } + is FirConstructor -> false + is FirProperty -> baseDeclaration is FirProperty && isOverriddenPropertyCheck(overrideCandidate, baseDeclaration) + is FirField -> false + else -> error("Unknown fir callable type: $overrideCandidate, $baseDeclaration") } + } - val self = (this as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration<*> - val overriding = seen.firstOrNull { - val member = (it as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration<*> - self.modality != Modality.FINAL - && similarFunctionsOrBothProperties(member, self) + // Receiver is super-type function here + protected open fun FirCallableSymbol<*>.getOverridden(overrideCandidates: Set>): FirCallableSymbol<*>? { + if (overrideByBase.containsKey(this)) return overrideByBase[this] + + val baseDeclaration = (this as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration<*> + val override = overrideCandidates.firstOrNull { + val overrideCandidate = (it as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration<*> + baseDeclaration.modality != Modality.FINAL && similarFunctionsOrBothProperties(overrideCandidate, baseDeclaration) } // TODO: two or more overrides for one fun? - overrides[this] = overriding - return overriding + overrideByBase[this] = override + return override } } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteScope.kt new file mode 100644 index 00000000000..4b9586d4f22 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteScope.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2019 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.scopes.impl + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.scopes.FirPosition +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.name.Name + +abstract class AbstractFirUseSiteScope( + session: FirSession, + protected val superTypesScope: FirSuperTypeScope, + protected val declaredMemberScope: FirScope +) : AbstractFirOverrideScope(session) { + override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction { + val overrideCandidates = mutableSetOf>() + if (!declaredMemberScope.processFunctionsByName(name) { + overrideCandidates += it + processor(it) + } + ) return ProcessorAction.STOP + + return superTypesScope.processFunctionsByName(name) { + + val overriddenBy = it.getOverridden(overrideCandidates) + if (overriddenBy == null) { + processor(it) + } else { + ProcessorAction.NEXT + } + } + } + + override fun processClassifiersByName(name: Name, position: FirPosition, processor: (FirClassifierSymbol<*>) -> Boolean): Boolean { + return declaredMemberScope.processClassifiersByName(name, position, processor) + } +} \ 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 01555e58030..349052ccd1d 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 @@ -6,40 +6,18 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.scopes.FirPosition 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.impl.FirCallableSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.name.Name class FirClassUseSiteScope( session: FirSession, - private val superTypesScope: FirSuperTypeScope, - private val declaredMemberScope: FirScope -) : AbstractFirOverrideScope(session) { - - override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction { - val seen = mutableSetOf>() - if (!declaredMemberScope.processFunctionsByName(name) { - seen += it - processor(it) - } - ) return STOP - - return superTypesScope.processFunctionsByName(name) { - - val overriddenBy = it.isOverridden(seen) - if (overriddenBy == null) { - processor(it) - } else { - NEXT - } - } - } + superTypesScope: FirSuperTypeScope, + declaredMemberScope: FirScope +) : AbstractFirUseSiteScope(session, superTypesScope, declaredMemberScope) { override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction { val seen = mutableSetOf>() @@ -51,7 +29,7 @@ class FirClassUseSiteScope( return superTypesScope.processPropertiesByName(name) { - val overriddenBy = it.isOverridden(seen) + val overriddenBy = it.getOverridden(seen) if (overriddenBy == null) { processor(it) } else { @@ -59,10 +37,6 @@ class FirClassUseSiteScope( } } } - - override fun processClassifiersByName(name: Name, position: FirPosition, processor: (FirClassifierSymbol<*>) -> Boolean): Boolean { - return declaredMemberScope.processClassifiersByName(name, position, processor) - } } 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 index cc9d53eb528..3ac7bba1035 100644 --- 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 @@ -31,7 +31,7 @@ class FirSuperTypeScope( for (scope in scopes) { if (scope.processFunctionsByName(name) { functionSymbol -> empty = false - if (functionSymbol !in accepted && functionSymbol.isOverridden(accepted) == null) { + if (functionSymbol !in accepted && functionSymbol.getOverridden(accepted) == null) { pending += functionSymbol processor(functionSymbol) } else { @@ -60,7 +60,7 @@ class FirSuperTypeScope( for (scope in scopes) { if (scope.processPropertiesByName(name) { empty = false - if (it !in accepted && it.isOverridden(accepted) == null) { + if (it !in accepted && it.getOverridden(accepted) == null) { pending += it processor(it) } else {