[FIR] Calculate property setters visibilities for intersections properly

Basically, just calculate them the same
way it's done for other members.

`chooseIntersectionVisibilityForSymbolsOrNull`
is named like this to prevent a JVM clash.

^KT-66046 Fixed
This commit is contained in:
Nikolay Lunyak
2024-03-06 15:14:44 +02:00
committed by Space Team
parent b7926b68ab
commit 7ecbaf7d1e
12 changed files with 88 additions and 84 deletions
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.scopes.MemberWithBaseScope
import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -51,8 +50,8 @@ class JavaOverridabilityRules(session: FirSession) : PlatformSpecificOverridabil
private fun FirCallableDeclaration.isOriginallyFromJava(): Boolean = unwrapFakeOverrides().origin == FirDeclarationOrigin.Enhancement private fun FirCallableDeclaration.isOriginallyFromJava(): Boolean = unwrapFakeOverrides().origin == FirDeclarationOrigin.Enhancement
override fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility( override fun chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>, overrides: Collection<FirCallableSymbol<*>>,
dispatchClassSymbol: FirRegularClassSymbol?, dispatchClassSymbol: FirRegularClassSymbol?,
): Visibility = javaOverrideChecker.chooseIntersectionVisibility(extractedOverrides, dispatchClassSymbol) ): Visibility = javaOverrideChecker.chooseIntersectionVisibility(overrides, dispatchClassSymbol)
} }
@@ -25,11 +25,8 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.MemberWithBaseScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractOverrideChecker import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.scopes.impl.chooseIntersectionVisibilityOrNull
import org.jetbrains.kotlin.fir.scopes.impl.isAbstract
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptorRepresentation import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptorRepresentation
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -370,25 +367,23 @@ class JavaOverrideChecker internal constructor(
return overridesMutableCollectionRemove return overridesMutableCollectionRemove
} }
override fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility( override fun chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>, overrides: Collection<FirCallableSymbol<*>>,
dispatchClassSymbol: FirRegularClassSymbol?, dispatchClassSymbol: FirRegularClassSymbol?,
): Visibility { ): Visibility {
val nonSubsumed = extractedOverrides.getNonSubsumedNonPhantomOverriddenSymbols()
// In Java it's OK to inherit multiple implementations of the same function // In Java it's OK to inherit multiple implementations of the same function
// from the supertypes as long as there's an implementation from a class. // from the supertypes as long as there's an implementation from a class.
// We shouldn't reject green Java code. // We shouldn't reject green Java code.
if (dispatchClassSymbol?.fir is FirJavaClass) { if (dispatchClassSymbol?.fir is FirJavaClass) {
val nonAbstractFromClass = nonSubsumed.find { val nonAbstractFromClass = overrides.find {
!it.isAbstract && it.member.dispatchReceiverClassLookupTagOrNull() !it.isAbstractAccordingToRawStatus && it.dispatchReceiverClassLookupTagOrNull()
?.toSymbol(session)?.classKind == ClassKind.CLASS ?.toSymbol(session)?.classKind == ClassKind.CLASS
} }
if (nonAbstractFromClass != null) { if (nonAbstractFromClass != null) {
return nonAbstractFromClass.member.rawStatus.visibility return nonAbstractFromClass.rawStatus.visibility
} }
} }
return chooseIntersectionVisibilityOrNull(nonSubsumed) ?: Visibilities.Unknown return chooseIntersectionVisibilityOrNull(overrides) ?: Visibilities.Unknown
} }
} }
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
import org.jetbrains.kotlin.fir.scopes.MemberWithBaseScope
import org.jetbrains.kotlin.fir.scopes.impl.* import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
@@ -38,12 +37,11 @@ class FirNativeOverrideChecker(private val session: FirSession) : FirOverrideChe
// KT-57640: There's no necessity to implement platform-dependent overridability check for properties // KT-57640: There's no necessity to implement platform-dependent overridability check for properties
standardOverrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration) standardOverrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration)
override fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility( override fun chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>, overrides: Collection<FirCallableSymbol<*>>,
dispatchClassSymbol: FirRegularClassSymbol?, dispatchClassSymbol: FirRegularClassSymbol?,
): Visibility { ): Visibility {
val nonSubsumed = extractedOverrides.getNonSubsumedNonPhantomOverriddenSymbols() return chooseIntersectionVisibilityOrNull(overrides) { it.isAbstractAccordingToRawStatus || it.isObjCClassProperty(session) }
return chooseIntersectionVisibilityOrNull(nonSubsumed) { it.isAbstract || it.member.isObjCClassProperty(session) }
?: Visibilities.Unknown ?: Visibilities.Unknown
} }
@@ -35,11 +35,11 @@ class FirIntersectionScopeOverrideChecker(session: FirSession) : FirOverrideChec
return standardOverrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration) return standardOverrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration)
} }
override fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility( override fun chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>, overrides: Collection<FirCallableSymbol<*>>,
dispatchClassSymbol: FirRegularClassSymbol?, dispatchClassSymbol: FirRegularClassSymbol?,
): Visibility { ): Visibility {
platformSpecificOverridabilityRules?.chooseIntersectionVisibility(extractedOverrides, dispatchClassSymbol)?.let { return it } platformSpecificOverridabilityRules?.chooseIntersectionVisibility(overrides, dispatchClassSymbol)?.let { return it }
return standardOverrideChecker.chooseIntersectionVisibility(extractedOverrides, dispatchClassSymbol) return standardOverrideChecker.chooseIntersectionVisibility(overrides, dispatchClassSymbol)
} }
} }
@@ -27,8 +27,8 @@ interface FirOverrideChecker : FirSessionComponent {
baseDeclaration: FirProperty baseDeclaration: FirProperty
): Boolean ): Boolean
fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility( fun chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>, overrides: Collection<FirCallableSymbol<*>>,
dispatchClassSymbol: FirRegularClassSymbol?, dispatchClassSymbol: FirRegularClassSymbol?,
): Visibility ): Visibility
} }
@@ -26,8 +26,8 @@ interface PlatformSpecificOverridabilityRules : FirSessionComponent {
baseDeclaration: FirProperty baseDeclaration: FirProperty
): Boolean? ): Boolean?
fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility( fun chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>, overrides: Collection<FirCallableSymbol<*>>,
dispatchClassSymbol: FirRegularClassSymbol?, dispatchClassSymbol: FirRegularClassSymbol?,
): Visibility? ): Visibility?
} }
@@ -399,6 +399,7 @@ object FirFakeOverrideGenerator {
newReturnType: ConeKotlinType? = null, newReturnType: ConeKotlinType? = null,
newModality: Modality? = null, newModality: Modality? = null,
newVisibility: Visibility? = null, newVisibility: Visibility? = null,
newSetterVisibility: Visibility? = null,
deferredReturnTypeCalculation: DeferredCallableCopyReturnType? = null, deferredReturnTypeCalculation: DeferredCallableCopyReturnType? = null,
newSource: KtSourceElement? = derivedClassLookupTag?.toSymbol(session)?.source, newSource: KtSourceElement? = derivedClassLookupTag?.toSymbol(session)?.source,
): FirProperty = buildProperty { ): FirProperty = buildProperty {
@@ -436,16 +437,19 @@ object FirFakeOverrideGenerator {
newSource = newSource ?: baseProperty.getter?.source, newSource = newSource ?: baseProperty.getter?.source,
) )
setter = baseProperty.setter?.buildCopyIfNeeded( setter = baseProperty.setter?.let { setter ->
moduleData = session.nullableModuleData ?: baseProperty.moduleData, setter.buildCopyIfNeeded(
origin = origin, moduleData = session.nullableModuleData ?: baseProperty.moduleData,
propertyReturnTypeRef = this@buildProperty.returnTypeRef, origin = origin,
propertySymbol = newSymbol, propertyReturnTypeRef = this@buildProperty.returnTypeRef,
dispatchReceiverType = dispatchReceiverType, propertySymbol = newSymbol,
derivedClassLookupTag = derivedClassLookupTag, dispatchReceiverType = dispatchReceiverType,
baseProperty = baseProperty, derivedClassLookupTag = derivedClassLookupTag,
newSource = newSource ?: baseProperty.setter?.source, baseProperty = baseProperty,
) newSource = newSource ?: baseProperty.setter?.source,
newSetterVisibility ?: setter.visibility,
)
}
}.apply { }.apply {
containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseProperty) } containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseProperty) }
} }
@@ -459,8 +463,9 @@ object FirFakeOverrideGenerator {
derivedClassLookupTag: ConeClassLikeLookupTag?, derivedClassLookupTag: ConeClassLikeLookupTag?,
baseProperty: FirProperty, baseProperty: FirProperty,
newSource: KtSourceElement? = source, newSource: KtSourceElement? = source,
newVisibility: Visibility = visibility,
) = when { ) = when {
annotations.isNotEmpty() || visibility != baseProperty.visibility -> buildCopy( annotations.isNotEmpty() || newVisibility != baseProperty.visibility -> buildCopy(
moduleData, moduleData,
origin, origin,
propertyReturnTypeRef, propertyReturnTypeRef,
@@ -469,6 +474,7 @@ object FirFakeOverrideGenerator {
derivedClassLookupTag, derivedClassLookupTag,
baseProperty, baseProperty,
newSource, newSource,
newVisibility,
) )
else -> null else -> null
} }
@@ -482,13 +488,14 @@ object FirFakeOverrideGenerator {
derivedClassLookupTag: ConeClassLikeLookupTag?, derivedClassLookupTag: ConeClassLikeLookupTag?,
baseProperty: FirProperty, baseProperty: FirProperty,
newSource: KtSourceElement? = source, newSource: KtSourceElement? = source,
newVisibility: Visibility = visibility,
) = when (this) { ) = when (this) {
is FirDefaultPropertyGetter -> FirDefaultPropertyGetter( is FirDefaultPropertyGetter -> FirDefaultPropertyGetter(
source = newSource, source = newSource,
moduleData = moduleData, moduleData = moduleData,
origin = origin, origin = origin,
propertyTypeRef = propertyReturnTypeRef, propertyTypeRef = propertyReturnTypeRef,
visibility = visibility, visibility = newVisibility,
propertySymbol = propertySymbol, propertySymbol = propertySymbol,
modality = modality ?: Modality.FINAL, modality = modality ?: Modality.FINAL,
effectiveVisibility = effectiveVisibility, effectiveVisibility = effectiveVisibility,
@@ -501,7 +508,7 @@ object FirFakeOverrideGenerator {
moduleData = moduleData, moduleData = moduleData,
origin = origin, origin = origin,
propertyTypeRef = propertyReturnTypeRef, propertyTypeRef = propertyReturnTypeRef,
visibility = visibility, visibility = newVisibility,
propertySymbol = propertySymbol, propertySymbol = propertySymbol,
modality = modality ?: Modality.FINAL, modality = modality ?: Modality.FINAL,
effectiveVisibility = effectiveVisibility, effectiveVisibility = effectiveVisibility,
@@ -518,6 +525,7 @@ object FirFakeOverrideGenerator {
this.dispatchReceiverType = dispatchReceiverType this.dispatchReceiverType = dispatchReceiverType
this.body = null this.body = null
resolvePhase = origin.resolvePhaseForCopy resolvePhase = origin.resolvePhaseForCopy
this.status = status.copy(visibility = newVisibility)
}.also { }.also {
if (it.isSetter) { if (it.isSetter) {
val originalParameter = it.valueParameters.first() val originalParameter = it.valueParameters.first()
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
@@ -64,40 +65,54 @@ fun <D : FirCallableSymbol<*>> overrides(
} }
inline fun chooseIntersectionVisibilityOrNull( inline fun chooseIntersectionVisibilityOrNull(
nonSubsumedOverrides: List<MemberWithBaseScope<FirCallableSymbol<*>>>, nonSubsumedOverrides: Collection<FirCallableSymbol<*>>,
isAbstract: (MemberWithBaseScope<FirCallableSymbol<*>>) -> Boolean = MemberWithBaseScope<FirCallableSymbol<*>>::isAbstract, isAbstract: (FirCallableSymbol<*>) -> Boolean = FirCallableSymbol<*>::isAbstractAccordingToRawStatus,
): Visibility? = chooseIntersectionVisibilityOrNull(
nonSubsumedOverrides,
toSymbol = { it },
isAbstract,
)
inline fun <D> chooseIntersectionVisibilityOrNull(
nonSubsumedOverrides: Collection<D>,
toSymbol: (D) -> FirCallableSymbol<*>,
isAbstract: (D) -> Boolean,
): Visibility? { ): Visibility? {
val nonAbstract = nonSubsumedOverrides.filter { val nonAbstract = nonSubsumedOverrides.filter {
// Kotlin's Cloneable interface contains phantom `protected open fun clone()`. // Kotlin's Cloneable interface contains phantom `protected open fun clone()`.
!isAbstract(it) && it.member.callableId != StandardClassIds.Callables.clone !isAbstract(it) && toSymbol(it).callableId != StandardClassIds.Callables.clone
} }
val allAreAbstract = nonAbstract.isEmpty() val allAreAbstract = nonAbstract.isEmpty()
if (allAreAbstract) { if (allAreAbstract) {
return findMaxVisibilityOrNull(nonSubsumedOverrides) return findMaxVisibilityOrNull(nonSubsumedOverrides, toSymbol)
} }
return nonAbstract.singleOrNull()?.member?.rawStatus?.visibility return nonAbstract.singleOrNull()?.let(toSymbol)?.rawStatus?.visibility
} }
val MemberWithBaseScope<FirCallableSymbol<*>>.isAbstract: Boolean val FirCallableSymbol<*>.isAbstractAccordingToRawStatus: Boolean
get() { get() {
val responsibleDeclaration = when (this) {
!is FirPropertyAccessorSymbol -> this
else -> propertySymbol
}
// This function is expected to be called during FirResolvePhase.STATUS, // This function is expected to be called during FirResolvePhase.STATUS,
// meaning we can't yet access `resolvedStatus`, because it would require // meaning we can't yet access `resolvedStatus`, because it would require
// the same phase, but by this time we expect the statuses to have been // the same phase, but by this time we expect the statuses to have been
// calculated de-facto. // calculated de-facto.
require(member.rawStatus is FirResolvedDeclarationStatus) require(responsibleDeclaration.rawStatus is FirResolvedDeclarationStatus)
// Kotlin's Cloneable interface contains phantom `protected open fun clone()`. return responsibleDeclaration.rawStatus.modality == Modality.ABSTRACT
return member.rawStatus.modality == Modality.ABSTRACT
} }
fun <D : FirCallableSymbol<*>> findMaxVisibilityOrNull( inline fun <D> findMaxVisibilityOrNull(
extractedOverrides: Collection<MemberWithBaseScope<D>> extractedOverrides: Collection<D>,
toSymbol: (D) -> FirCallableSymbol<*>,
): Visibility? { ): Visibility? {
var maxVisibility: Visibility = Visibilities.Private var maxVisibility: Visibility = Visibilities.Private
for ((override) in extractedOverrides) { for (override in extractedOverrides) {
val visibility = (override.fir as FirMemberDeclaration).visibility val visibility = (toSymbol(override).fir as FirMemberDeclaration).visibility
val compare = Visibilities.compare(visibility, maxVisibility) ?: return null val compare = Visibilities.compare(visibility, maxVisibility) ?: return null
if (compare > 0) { if (compare > 0) {
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclaration import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclaration
import org.jetbrains.kotlin.fir.scopes.MemberWithBaseScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
@@ -162,11 +161,10 @@ class FirStandardOverrideChecker(private val session: FirSession) : FirAbstractO
} }
} }
override fun <D : FirCallableSymbol<*>> chooseIntersectionVisibility( override fun chooseIntersectionVisibility(
extractedOverrides: Collection<MemberWithBaseScope<D>>, overrides: Collection<FirCallableSymbol<*>>,
dispatchClassSymbol: FirRegularClassSymbol?, dispatchClassSymbol: FirRegularClassSymbol?,
): Visibility { ): Visibility {
val nonSubsumed = extractedOverrides.getNonSubsumedNonPhantomOverriddenSymbols() return chooseIntersectionVisibilityOrNull(overrides) ?: Visibilities.Unknown
return chooseIntersectionVisibilityOrNull(nonSubsumed) ?: Visibilities.Unknown
} }
} }
@@ -215,7 +215,8 @@ class FirTypeIntersectionScopeContext(
containsMultipleNonSubsumed: Boolean, containsMultipleNonSubsumed: Boolean,
): MemberWithBaseScope<FirCallableSymbol<*>> { ): MemberWithBaseScope<FirCallableSymbol<*>> {
val newModality = chooseIntersectionOverrideModality(extractedOverrides.flatMap { it.flattenIntersectionsRecursively() }.nonSubsumed()) val newModality = chooseIntersectionOverrideModality(extractedOverrides.flatMap { it.flattenIntersectionsRecursively() }.nonSubsumed())
val newVisibility = overrideChecker.chooseIntersectionVisibility(extractedOverrides, dispatchClassSymbol) val nonSubsumedNonPhantomOverrides = extractedOverrides.getNonSubsumedNonPhantomOverriddenSymbols().map { it.member }
val newVisibility = overrideChecker.chooseIntersectionVisibility(nonSubsumedNonPhantomOverrides, dispatchClassSymbol)
val mostSpecificSymbols = mostSpecific.map { it.member } val mostSpecificSymbols = mostSpecific.map { it.member }
val extractedOverridesSymbols = extractedOverrides.map { it.member } val extractedOverridesSymbols = extractedOverrides.map { it.member }
val key = mostSpecific.first() val key = mostSpecific.first()
@@ -227,7 +228,8 @@ class FirTypeIntersectionScopeContext(
is FirPropertySymbol -> is FirPropertySymbol ->
createIntersectionOverrideProperty( createIntersectionOverrideProperty(
mostSpecificSymbols, extractedOverridesSymbols, newModality, newVisibility, containsMultipleNonSubsumed mostSpecificSymbols, extractedOverridesSymbols, nonSubsumedNonPhantomOverrides, newModality,
newVisibility, containsMultipleNonSubsumed,
) )
is FirFieldSymbol -> { is FirFieldSymbol -> {
@@ -368,6 +370,7 @@ class FirTypeIntersectionScopeContext(
private fun createIntersectionOverrideProperty( private fun createIntersectionOverrideProperty(
mostSpecific: Collection<FirCallableSymbol<*>>, mostSpecific: Collection<FirCallableSymbol<*>>,
overrides: Collection<FirCallableSymbol<*>>, overrides: Collection<FirCallableSymbol<*>>,
nonSubsumedNonPhantomOverrides: List<FirCallableSymbol<*>>,
newModality: Modality?, newModality: Modality?,
newVisibility: Visibility, newVisibility: Visibility,
containsMultipleNonSubsumed: Boolean, containsMultipleNonSubsumed: Boolean,
@@ -378,6 +381,14 @@ class FirTypeIntersectionScopeContext(
containsMultipleNonSubsumed, containsMultipleNonSubsumed,
::FirIntersectionOverridePropertySymbol, ::FirIntersectionOverridePropertySymbol,
) { symbol, fir, deferredReturnTypeCalculation, returnType -> ) { symbol, fir, deferredReturnTypeCalculation, returnType ->
// Only setters's visibilities are calculated properly, because
// getters' visibilities must be the same as the ones of their
// properties and those we've already calculated.
val setters = nonSubsumedNonPhantomOverrides.mapNotNull {
(it as? FirPropertySymbol)?.unwrapSubstitutionOverrides()?.setterSymbol
}
val setterVisibility = chooseIntersectionVisibilityOrNull(setters) ?: Visibilities.Unknown
FirFakeOverrideGenerator.createCopyForFirProperty( FirFakeOverrideGenerator.createCopyForFirProperty(
symbol, fir, derivedClassLookupTag = null, session, symbol, fir, derivedClassLookupTag = null, session,
FirDeclarationOrigin.IntersectionOverride, FirDeclarationOrigin.IntersectionOverride,
@@ -390,6 +401,7 @@ class FirTypeIntersectionScopeContext(
// anyway and their uses should result in an overload resolution error. // anyway and their uses should result in an overload resolution error.
newReturnType = returnType, newReturnType = returnType,
newSource = dispatchReceiverType.toSymbol(session)?.source, newSource = dispatchReceiverType.toSymbol(session)?.source,
newSetterVisibility = setterVisibility,
) )
} }
} }
@@ -1,22 +0,0 @@
// ISSUE: KT-66046
abstract class I1 {
abstract var a: Int
protected set
}
interface I2 {
var a: Int
}
abstract class <!CANNOT_WEAKEN_ACCESS_PRIVILEGE!>C<!> : I1(), I2
abstract class I3 {
protected abstract fun foo(): Int
}
interface I4 {
fun foo(): Int
}
abstract class B : I3(), I4
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ISSUE: KT-66046 // ISSUE: KT-66046
abstract class I1 { abstract class I1 {