[FIR] Properly calculate visibilities
`testIntersectionOfPrimitiveBasedFunctions` is fine, because we deprecate this already in ^KT-63243. `CANNOT_INFER_VISIBILITY` is positioned as `DECLARATION_NAME`, just in case we decide for some reason that we do want to report it along with `MANY_*_NOT_IMPLEMENTED`. In that case, we'd get a problem that their bounds overlap, but not completely contain one another. ^KT-63741 Fixed ^KT-59400 Fixed
This commit is contained in:
committed by
Space Team
parent
7056ad5325
commit
8f8c7fe7cf
+40
-4
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
@@ -321,17 +322,52 @@ class FirTypeIntersectionScopeContext(
|
||||
|
||||
private fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility(
|
||||
extractedOverrides: Collection<MemberWithBaseScope<D>>
|
||||
): Visibility {
|
||||
): Visibility = chooseIntersectionVisibilityOrNull(extractedOverrides) ?: Visibilities.Unknown
|
||||
|
||||
private fun <D : FirCallableSymbol<*>> chooseIntersectionVisibilityOrNull(
|
||||
extractedOverrides: Collection<MemberWithBaseScope<D>>
|
||||
): Visibility? {
|
||||
val overridesWithoutIntersections = extractedOverrides.flatMap { it.flattenIntersectionsRecursively() }
|
||||
val nonSubsumed = overridesWithoutIntersections.nonSubsumed().filterOutDuplicates()
|
||||
val nonAbstract = nonSubsumed.filter {
|
||||
require(it.member.rawStatus is FirResolvedDeclarationStatus) {
|
||||
"We expect that to be true already, but we can't yet call resolvedStatus"
|
||||
}
|
||||
// Kotlin's Cloneable interface contains phantom `protected open fun clone()`.
|
||||
it.member.rawStatus.modality != Modality.ABSTRACT && it.member.callableId != StandardClassIds.Callables.clone
|
||||
}
|
||||
val allAreAbstract = nonAbstract.isEmpty()
|
||||
|
||||
if (allAreAbstract) {
|
||||
return findMaxVisibilityOrNull(nonSubsumed)
|
||||
}
|
||||
|
||||
if (nonAbstract.size >= 2) {
|
||||
return null
|
||||
}
|
||||
|
||||
return nonAbstract.single().member.rawStatus.visibility
|
||||
}
|
||||
|
||||
private fun <D : FirCallableSymbol<*>> List<MemberWithBaseScope<D>>.filterOutDuplicates(): List<MemberWithBaseScope<D>> {
|
||||
val uniqueSymbols = mutableSetOf<FirCallableSymbol<*>>()
|
||||
return filter { uniqueSymbols.add(it.member.fir.unwrapSubstitutionOverrides().symbol) }
|
||||
}
|
||||
|
||||
private fun <D : FirCallableSymbol<*>> findMaxVisibilityOrNull(
|
||||
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
|
||||
val compare = Visibilities.compare(visibility, maxVisibility) ?: return null
|
||||
|
||||
if (compare > 0) {
|
||||
maxVisibility = visibility
|
||||
}
|
||||
}
|
||||
|
||||
return maxVisibility
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user