diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt index 59810b51651..ecd28444e76 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt @@ -5,11 +5,13 @@ package org.jetbrains.kotlin.fir.scopes.impl +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.* -import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl +import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty import org.jetbrains.kotlin.fir.resolve.ScopeSession @@ -316,14 +318,16 @@ class FirClassSubstitutionScope( newParameterTypes: List? = null, newTypeParameters: List? = null, newReceiverType: ConeKotlinType? = null, - newReturnType: ConeKotlinType? = null + newReturnType: ConeKotlinType? = null, + newModality: Modality? = null, + newVisibility: Visibility? = null, ): FirSimpleFunction { return buildSimpleFunction { source = baseFunction.source this.session = session this.origin = origin name = baseFunction.name - status = baseFunction.status.withExpect(isExpect) + status = baseFunction.status.updatedStatus(isExpect, newModality, newVisibility) symbol = newSymbol resolvePhase = baseFunction.resolvePhase @@ -349,7 +353,7 @@ class FirClassSubstitutionScope( this.session = session origin = FirDeclarationOrigin.FakeOverride receiverTypeRef = baseConstructor.receiverTypeRef?.withReplacedConeType(null) - status = baseConstructor.status.withExpect(isExpect) + status = baseConstructor.status.updatedStatus(isExpect) symbol = fakeOverrideSymbol resolvePhase = baseConstructor.resolvePhase @@ -452,6 +456,8 @@ class FirClassSubstitutionScope( newTypeParameters: List? = null, newReceiverType: ConeKotlinType? = null, newReturnType: ConeKotlinType? = null, + newModality: Modality? = null, + newVisibility: Visibility? = null, ): FirProperty { return buildProperty { source = baseProperty.source @@ -461,7 +467,8 @@ class FirClassSubstitutionScope( isVar = baseProperty.isVar this.symbol = newSymbol isLocal = false - status = baseProperty.status.withExpect(isExpect) + status = baseProperty.status.updatedStatus(isExpect, newModality, newVisibility) + resolvePhase = baseProperty.resolvePhase typeParameters += configureAnnotationsTypeParametersAndSignature( baseProperty, @@ -574,11 +581,16 @@ class FirClassSubstitutionScope( }.symbol } - private fun FirDeclarationStatus.withExpect(isExpect: Boolean): FirDeclarationStatus { - return if (this.isExpect == isExpect) { + private fun FirDeclarationStatus.updatedStatus( + isExpect: Boolean, + newModality: Modality? = null, + newVisibility: Visibility? = null, + ): FirDeclarationStatus { + return if (this.isExpect == isExpect && newModality == null && newVisibility == null) { this } else { - FirResolvedDeclarationStatusImpl(visibility, modality!!).apply { + require(this is FirDeclarationStatusImpl) { "Unexpected class ${this::class}" } + this.resolved(newVisibility ?: visibility, newModality ?: modality!!).apply { this.isExpect = isExpect } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt index 1ce1059c1fa..25833e88aac 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt @@ -5,8 +5,10 @@ package org.jetbrains.kotlin.fir.scopes.impl -import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker @@ -38,7 +40,8 @@ class FirTypeIntersectionScope private constructor( private val typeContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = false, session) - private val overriddenSymbols: MutableMap, Collection>>> = mutableMapOf() + private val overriddenSymbols: MutableMap, Collection>>> = + mutableMapOf() private val intersectionOverrides: MutableMap, MemberWithBaseScope>> = mutableMapOf() @@ -97,21 +100,23 @@ class FirTypeIntersectionScope private constructor( while (allMembersWithScope.isNotEmpty()) { val maxByVisibility = findMemberWithMaxVisibility(allMembersWithScope) - val extractedOverrides = extractBothWaysOverridable(maxByVisibility, allMembersWithScope) + val extractBothWaysWithPrivate = extractBothWaysOverridable(maxByVisibility, allMembersWithScope) + val extractedOverrides = extractBothWaysWithPrivate.filterNot { + Visibilities.isPrivate((it.member.fir as FirMemberDeclaration).visibility) + }.takeIf { it.isNotEmpty() } ?: extractBothWaysWithPrivate val (mostSpecific, scopeForMostSpecific) = selectMostSpecificMember(extractedOverrides) if (extractedOverrides.size > 1) { val intersectionOverride = intersectionOverrides.getOrPut(mostSpecific) { + val newModality = chooseIntersectionOverrideModality(extractedOverrides) + val newVisibility = chooseIntersectionVisibility(extractedOverrides) @Suppress("UNCHECKED_CAST") when (mostSpecific) { is FirNamedFunctionSymbol -> { - createIntersectionOverride( - mostSpecific, - extractedOverrides as Collection> - ) + createIntersectionOverride(mostSpecific, newModality, newVisibility) } is FirPropertySymbol -> { - createIntersectionOverride(mostSpecific) + createIntersectionOverride(mostSpecific, newModality, newVisibility) } else -> { throw IllegalStateException("Should not be here") @@ -130,9 +135,32 @@ class FirTypeIntersectionScope private constructor( return true } + private fun > chooseIntersectionOverrideModality( + extractedOverrides: Collection> + ): Modality { + return extractedOverrides.minOf { (it.member.fir as FirMemberDeclaration).modality ?: Modality.ABSTRACT } + } + + private fun > chooseIntersectionVisibility( + extractedOverrides: Collection> + ): Visibility { + var maxVisibility: Visibility = Visibilities.Private + for ((override) in extractedOverrides) { + val visibility = (override.fir as FirMemberDeclaration).visibility + // TODO: There is more complex logic at org.jetbrains.kotlin.resolve.OverridingUtil.resolveUnknownVisibilityForMember + // TODO: and org.jetbrains.kotlin.resolve.OverridingUtil.findMaxVisibility + val compare = Visibilities.compare(visibility, maxVisibility) ?: return Visibilities.DEFAULT_VISIBILITY + if (compare > 0) { + maxVisibility = visibility + } + } + return maxVisibility + } + private fun createIntersectionOverride( mostSpecific: FirNamedFunctionSymbol, - extractedOverrides: Collection> + newModality: Modality, + newVisibility: Visibility, ): FirNamedFunctionSymbol { val newSymbol = FirNamedFunctionSymbol( @@ -146,15 +174,23 @@ class FirTypeIntersectionScope private constructor( newSymbol, mostSpecificFunction, session, FirDeclarationOrigin.IntersectionOverride, mostSpecificFunction.isExpect, + newModality = newModality, + newVisibility = newVisibility, ) return newSymbol } - private fun createIntersectionOverride(mostSpecific: FirPropertySymbol): FirPropertySymbol { + private fun createIntersectionOverride( + mostSpecific: FirPropertySymbol, + newModality: Modality, + newVisibility: Visibility, + ): FirPropertySymbol { val newSymbol = FirPropertySymbol(mostSpecific.callableId, mostSpecific.isFakeOverride, mostSpecific, isIntersectionOverride = true) val mostSpecificProperty = mostSpecific.fir FirClassSubstitutionScope.createCopyForFirProperty( - newSymbol, mostSpecificProperty, mostSpecificProperty.session + newSymbol, mostSpecificProperty, mostSpecificProperty.session, + newModality = newModality, + newVisibility = newVisibility, ) return newSymbol } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt index d6c712fa377..5330639f5d5 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt @@ -166,7 +166,7 @@ open class FirDeclarationStatusImpl( return this } - fun resolved(visibility: Visibility, modality: Modality): FirDeclarationStatus { + fun resolved(visibility: Visibility, modality: Modality): FirResolvedDeclarationStatusImpl { return FirResolvedDeclarationStatusImpl(visibility, modality, flags) } }