FIR: Use refined visibility/modality for intersection overrides
This commit is contained in:
+20
-8
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+47
-11
@@ -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
|
||||
}
|
||||
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user