FIR: Use refined visibility/modality for intersection overrides

This commit is contained in:
Denis Zharkov
2020-09-23 14:26:18 +03:00
parent 20bf238c27
commit 9696fecab5
3 changed files with 68 additions and 20 deletions
@@ -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<ConeKotlinType?>? = null,
newTypeParameters: List<FirTypeParameter>? = 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<FirTypeParameter>? = 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
}
}
@@ -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<FirCallableSymbol<*>, Collection<MemberWithBaseScope<out FirCallableSymbol<*>>>> = mutableMapOf()
private val overriddenSymbols: MutableMap<FirCallableSymbol<*>, Collection<MemberWithBaseScope<out FirCallableSymbol<*>>>> =
mutableMapOf()
private val intersectionOverrides: MutableMap<FirCallableSymbol<*>, MemberWithBaseScope<out FirCallableSymbol<*>>> = 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<MemberWithBaseScope<FirNamedFunctionSymbol>>
)
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 <D : FirCallableSymbol<*>> chooseIntersectionOverrideModality(
extractedOverrides: Collection<MemberWithBaseScope<D>>
): Modality {
return extractedOverrides.minOf { (it.member.fir as FirMemberDeclaration).modality ?: Modality.ABSTRACT }
}
private fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>
): 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<MemberWithBaseScope<FirNamedFunctionSymbol>>
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
}
@@ -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)
}
}