diff --git a/core/compiler.common/src/org/jetbrains/kotlin/descriptors/EffectiveVisibility.kt b/core/compiler.common/src/org/jetbrains/kotlin/descriptors/EffectiveVisibility.kt index c7dc8a40497..c04a568c733 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/descriptors/EffectiveVisibility.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/descriptors/EffectiveVisibility.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors import org.jetbrains.kotlin.descriptors.EffectiveVisibility.Permissiveness import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeCheckerContext +import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext import org.jetbrains.kotlin.types.model.TypeConstructorMarker sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = false, val privateApi: Boolean = false) { @@ -27,7 +28,7 @@ sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = fals object Private : EffectiveVisibility("private", privateApi = true) { - override fun relation(other: EffectiveVisibility): Permissiveness = + override fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness = if (this == other || Local == other) Permissiveness.SAME else Permissiveness.LESS override fun toVisibility(): Visibility = Visibilities.Private @@ -35,14 +36,14 @@ sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = fals // Effectively same as Private object Local : EffectiveVisibility("local") { - override fun relation(other: EffectiveVisibility): Permissiveness = + override fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness = if (this == other || Private == other) Permissiveness.SAME else Permissiveness.LESS override fun toVisibility(): Visibility = Visibilities.Local } object Public : EffectiveVisibility("public", publicApi = true) { - override fun relation(other: EffectiveVisibility): Permissiveness = + override fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness = if (this == other) Permissiveness.SAME else Permissiveness.MORE override fun toVisibility(): Visibility = Visibilities.Public @@ -51,19 +52,21 @@ sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = fals abstract class InternalOrPackage protected constructor(internal: Boolean) : EffectiveVisibility( if (internal) "internal" else "public/*package*/" ) { - override fun relation(other: EffectiveVisibility): Permissiveness = when (other) { - Public -> Permissiveness.LESS - Private, Local, InternalProtectedBound, is InternalProtected -> Permissiveness.MORE - is InternalOrPackage -> Permissiveness.SAME - ProtectedBound, is Protected -> Permissiveness.UNKNOWN - } + override fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness = + when (other) { + Public -> Permissiveness.LESS + Private, Local, InternalProtectedBound, is InternalProtected -> Permissiveness.MORE + is InternalOrPackage -> Permissiveness.SAME + ProtectedBound, is Protected -> Permissiveness.UNKNOWN + } - override fun lowerBound(other: EffectiveVisibility) = when (other) { - Public -> this - Private, Local, InternalProtectedBound, is InternalOrPackage, is InternalProtected -> other - is Protected -> InternalProtected(other.containerTypeConstructor, other.typeContext) - ProtectedBound -> InternalProtectedBound - } + override fun lowerBound(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): EffectiveVisibility = + when (other) { + Public -> this + Private, Local, InternalProtectedBound, is InternalOrPackage, is InternalProtected -> other + is Protected -> InternalProtected(other.containerTypeConstructor) + ProtectedBound -> InternalProtectedBound + } } object Internal : InternalOrPackage(true) { @@ -74,10 +77,7 @@ sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = fals override fun toVisibility(): Visibility = Visibilities.Private } - class Protected( - val containerTypeConstructor: TypeConstructorMarker?, - val typeContext: AbstractTypeCheckerContext - ) : EffectiveVisibility("protected", publicApi = true) { + class Protected(val containerTypeConstructor: TypeConstructorMarker?) : EffectiveVisibility("protected", publicApi = true) { override fun equals(other: Any?) = (other is Protected && containerTypeConstructor == other.containerTypeConstructor) @@ -85,59 +85,66 @@ sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = fals override fun toString() = "${super.toString()} (in ${containerTypeConstructor ?: '?'})" - override fun relation(other: EffectiveVisibility): Permissiveness = when (other) { - Public -> Permissiveness.LESS - Private, Local, ProtectedBound, InternalProtectedBound -> Permissiveness.MORE - is Protected -> containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeContext) - is InternalProtected -> when (containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeContext)) { - // Protected never can be less permissive than internal & protected - Permissiveness.SAME, Permissiveness.MORE -> Permissiveness.MORE - Permissiveness.UNKNOWN, Permissiveness.LESS -> Permissiveness.UNKNOWN + override fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness = + when (other) { + Public -> Permissiveness.LESS + Private, Local, ProtectedBound, InternalProtectedBound -> Permissiveness.MORE + is Protected -> containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeCheckerContextProvider) + is InternalProtected -> when (containerRelation( + containerTypeConstructor, + other.containerTypeConstructor, + typeCheckerContextProvider + )) { + // Protected never can be less permissive than internal & protected + Permissiveness.SAME, Permissiveness.MORE -> Permissiveness.MORE + Permissiveness.UNKNOWN, Permissiveness.LESS -> Permissiveness.UNKNOWN + } + is InternalOrPackage -> Permissiveness.UNKNOWN } - is InternalOrPackage -> Permissiveness.UNKNOWN - } - override fun lowerBound(other: EffectiveVisibility) = when (other) { - Public -> this - Private, Local, ProtectedBound, InternalProtectedBound -> other - is Protected -> when (relation(other)) { - Permissiveness.SAME, Permissiveness.MORE -> this - Permissiveness.LESS -> other - Permissiveness.UNKNOWN -> ProtectedBound + override fun lowerBound(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): EffectiveVisibility = + when (other) { + Public -> this + Private, Local, ProtectedBound, InternalProtectedBound -> other + is Protected -> when (relation(other, typeCheckerContextProvider)) { + Permissiveness.SAME, Permissiveness.MORE -> this + Permissiveness.LESS -> other + Permissiveness.UNKNOWN -> ProtectedBound + } + is InternalProtected -> when (relation(other, typeCheckerContextProvider)) { + Permissiveness.LESS -> other + else -> InternalProtectedBound + } + is InternalOrPackage -> InternalProtected(containerTypeConstructor) } - is InternalProtected -> when (relation(other)) { - Permissiveness.LESS -> other - else -> InternalProtectedBound - } - is InternalOrPackage -> InternalProtected(containerTypeConstructor, typeContext) - } override fun toVisibility(): Visibility = Visibilities.Protected } // Lower bound for all protected visibilities object ProtectedBound : EffectiveVisibility("protected (in different classes)", publicApi = true) { - override fun relation(other: EffectiveVisibility): Permissiveness = when (other) { - Public, is Protected -> Permissiveness.LESS - Private, Local, InternalProtectedBound -> Permissiveness.MORE - ProtectedBound -> Permissiveness.SAME - is InternalOrPackage, is InternalProtected -> Permissiveness.UNKNOWN - } + override fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness = + when (other) { + Public, is Protected -> Permissiveness.LESS + Private, Local, InternalProtectedBound -> Permissiveness.MORE + ProtectedBound -> Permissiveness.SAME + is InternalOrPackage, is InternalProtected -> Permissiveness.UNKNOWN + } - override fun lowerBound(other: EffectiveVisibility) = when (other) { - Public, is Protected -> this - Private, Local, ProtectedBound, InternalProtectedBound -> other - is InternalOrPackage, is InternalProtected -> InternalProtectedBound - } + override fun lowerBound(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): EffectiveVisibility = + when (other) { + Public, is Protected -> this + Private, Local, ProtectedBound, InternalProtectedBound -> other + is InternalOrPackage, is InternalProtected -> InternalProtectedBound + } override fun toVisibility(): Visibility = Visibilities.Protected } // Lower bound for internal and protected(C) class InternalProtected( - val containerTypeConstructor: TypeConstructorMarker?, - val typeContext: AbstractTypeCheckerContext, - ) : EffectiveVisibility("internal & protected") { + val containerTypeConstructor: TypeConstructorMarker? + ) : EffectiveVisibility("internal & protected", publicApi = false) { override fun equals(other: Any?) = (other is InternalProtected && containerTypeConstructor == other.containerTypeConstructor) @@ -145,39 +152,50 @@ sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = fals override fun toString() = "${super.toString()} (in ${containerTypeConstructor ?: '?'})" - override fun relation(other: EffectiveVisibility): Permissiveness = when (other) { - Public, is InternalOrPackage -> Permissiveness.LESS - Private, Local, InternalProtectedBound -> Permissiveness.MORE - is InternalProtected -> containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeContext) - is Protected -> when (containerRelation(containerTypeConstructor, other.containerTypeConstructor, typeContext)) { - // Internal & protected never can be more permissive than just protected - Permissiveness.SAME, Permissiveness.LESS -> Permissiveness.LESS - Permissiveness.UNKNOWN, Permissiveness.MORE -> Permissiveness.UNKNOWN + override fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness = + when (other) { + Public, is InternalOrPackage -> Permissiveness.LESS + Private, Local, InternalProtectedBound -> Permissiveness.MORE + is InternalProtected -> containerRelation( + containerTypeConstructor, + other.containerTypeConstructor, + typeCheckerContextProvider + ) + is Protected -> when (containerRelation( + containerTypeConstructor, + other.containerTypeConstructor, + typeCheckerContextProvider + )) { + // Internal & protected never can be more permissive than just protected + Permissiveness.SAME, Permissiveness.LESS -> Permissiveness.LESS + Permissiveness.UNKNOWN, Permissiveness.MORE -> Permissiveness.UNKNOWN + } + ProtectedBound -> Permissiveness.UNKNOWN } - ProtectedBound -> Permissiveness.UNKNOWN - } - override fun lowerBound(other: EffectiveVisibility) = when (other) { - Public, is InternalOrPackage -> this - Private, Local, InternalProtectedBound -> other - is Protected, is InternalProtected -> when (relation(other)) { - Permissiveness.SAME, Permissiveness.MORE -> this - Permissiveness.LESS -> other - Permissiveness.UNKNOWN -> InternalProtectedBound + override fun lowerBound(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): EffectiveVisibility = + when (other) { + Public, is InternalOrPackage -> this + Private, Local, InternalProtectedBound -> other + is Protected, is InternalProtected -> when (relation(other, typeCheckerContextProvider)) { + Permissiveness.SAME, Permissiveness.MORE -> this + Permissiveness.LESS -> other + Permissiveness.UNKNOWN -> InternalProtectedBound + } + ProtectedBound -> InternalProtectedBound } - ProtectedBound -> InternalProtectedBound - } override fun toVisibility(): Visibility = Visibilities.Private } // Lower bound for internal and protected lower bound object InternalProtectedBound : EffectiveVisibility("internal & protected (in different classes)") { - override fun relation(other: EffectiveVisibility): Permissiveness = when (other) { - Public, is Protected, is InternalProtected, ProtectedBound, is InternalOrPackage -> Permissiveness.LESS - Private, Local -> Permissiveness.MORE - InternalProtectedBound -> Permissiveness.SAME - } + override fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness = + when (other) { + Public, is Protected, is InternalProtected, ProtectedBound, is InternalOrPackage -> Permissiveness.LESS + Private, Local -> Permissiveness.MORE + InternalProtectedBound -> Permissiveness.SAME + } override fun toVisibility(): Visibility = Visibilities.Private } @@ -189,15 +207,16 @@ sealed class EffectiveVisibility(val name: String, val publicApi: Boolean = fals UNKNOWN } - abstract fun relation(other: EffectiveVisibility): Permissiveness + abstract fun relation(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): Permissiveness abstract fun toVisibility(): Visibility - open fun lowerBound(other: EffectiveVisibility) = when (relation(other)) { - Permissiveness.SAME, Permissiveness.LESS -> this - Permissiveness.MORE -> other - Permissiveness.UNKNOWN -> Private - } + open fun lowerBound(other: EffectiveVisibility, typeCheckerContextProvider: TypeCheckerProviderContext): EffectiveVisibility = + when (relation(other, typeCheckerContextProvider)) { + Permissiveness.SAME, Permissiveness.LESS -> this + Permissiveness.MORE -> other + Permissiveness.UNKNOWN -> Private + } } enum class RelationToType(val description: String) { @@ -217,14 +236,18 @@ enum class RelationToType(val description: String) { internal fun containerRelation( first: TypeConstructorMarker?, second: TypeConstructorMarker?, - typeContext: AbstractTypeCheckerContext + typeCheckerContextProvider: TypeCheckerProviderContext ): Permissiveness { return when { first == null || second == null -> Permissiveness.UNKNOWN first == second -> Permissiveness.SAME - AbstractTypeChecker.isSubtypeOfClass(typeContext, first, second) -> Permissiveness.LESS - AbstractTypeChecker.isSubtypeOfClass(typeContext, second, first) -> Permissiveness.MORE + AbstractTypeChecker.isSubtypeOfClass(typeCheckerContextProvider.createTypeCheckerContext(), first, second) -> Permissiveness.LESS + AbstractTypeChecker.isSubtypeOfClass(typeCheckerContextProvider.createTypeCheckerContext(), second, first) -> Permissiveness.MORE else -> Permissiveness.UNKNOWN } } +private fun TypeCheckerProviderContext.createTypeCheckerContext(): AbstractTypeCheckerContext = newBaseTypeCheckerContext( + errorTypesEqualToAnything = false, + stubTypesEqualToAnything = true +) diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/EffectiveVisibilityUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/EffectiveVisibilityUtils.kt index 509a78f6547..02679625181 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/EffectiveVisibilityUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/EffectiveVisibilityUtils.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.descriptors import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext +import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext fun EffectiveVisibility.toDescriptorVisibility(): DescriptorVisibility = DescriptorVisibilities.toDescriptorVisibility(toVisibility()) @@ -22,8 +22,7 @@ private fun DescriptorVisibility.forVisibility(descriptor: DeclarationDescriptor when (this) { DescriptorVisibilities.PRIVATE, DescriptorVisibilities.PRIVATE_TO_THIS, DescriptorVisibilities.INVISIBLE_FAKE -> EffectiveVisibility.Private DescriptorVisibilities.PROTECTED -> EffectiveVisibility.Protected( - (descriptor.containingDeclaration as? ClassDescriptor)?.defaultType?.constructor, - ClassicTypeCheckerContext(errorTypeEqualsToAnything = false) + (descriptor.containingDeclaration as? ClassDescriptor)?.defaultType?.constructor ) DescriptorVisibilities.INTERNAL -> if (!checkPublishedApi || !descriptor.isPublishedApi() @@ -69,7 +68,7 @@ private fun KotlinType.dependentDescriptors(types: Set, ownRelation: private fun Set.leastPermissive(base: EffectiveVisibility): DescriptorWithRelation? { for (descriptorWithRelation in this) { val currentVisibility = descriptorWithRelation.effectiveVisibility() - when (currentVisibility.relation(base)) { + when (currentVisibility.relation(base, SimpleClassicTypeSystemContext)) { EffectiveVisibility.Permissiveness.LESS, EffectiveVisibility.Permissiveness.UNKNOWN -> { return descriptorWithRelation } @@ -83,11 +82,14 @@ private fun Set.leastPermissive(base: EffectiveVisibilit fun KotlinType.leastPermissiveDescriptor(base: EffectiveVisibility) = dependentDescriptors().leastPermissive(base) fun DeclarationDescriptorWithVisibility.effectiveVisibility( - visibility: DescriptorVisibility = this.visibility, checkPublishedApi: Boolean = false + visibility: DescriptorVisibility = this.visibility, + checkPublishedApi: Boolean = false ): EffectiveVisibility = lowerBound( visibility.effectiveVisibility(this, checkPublishedApi), (this.containingDeclaration as? ClassDescriptor)?.effectiveVisibility(checkPublishedApi) ?: EffectiveVisibility.Public ) -private fun lowerBound(first: EffectiveVisibility, second: EffectiveVisibility): EffectiveVisibility = first.lowerBound(second) +private fun lowerBound(first: EffectiveVisibility, second: EffectiveVisibility): EffectiveVisibility { + return first.lowerBound(second, SimpleClassicTypeSystemContext) +} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityOnExposureFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityOnExposureFactory.kt index 1b581080dd0..ea97485b691 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityOnExposureFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityOnExposureFactory.kt @@ -18,8 +18,8 @@ package org.jetbrains.kotlin.idea.quickfix import com.intellij.codeInsight.intention.IntentionAction import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.EffectiveVisibility.Permissiveness.LESS import org.jetbrains.kotlin.descriptors.DescriptorVisibilities.* +import org.jetbrains.kotlin.descriptors.EffectiveVisibility.Permissiveness.LESS import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3 import org.jetbrains.kotlin.idea.core.toDescriptor @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext import java.util.* object ChangeVisibilityOnExposureFactory : KotlinIntentionActionsFactory() { @@ -58,7 +59,7 @@ object ChangeVisibilityOnExposureFactory : KotlinIntentionActionsFactory() { DescriptorToSourceUtils.getSourceFromDescriptor(exposedDescriptor) as? KtModifierListOwner ?: return emptyList() val exposedVisibility = exposedDiagnostic.c val userVisibility = exposedDiagnostic.a - val (targetUserVisibility, targetExposedVisibility) = when (exposedVisibility.relation(userVisibility)) { + val (targetUserVisibility, targetExposedVisibility) = when (exposedVisibility.relation(userVisibility, SimpleClassicTypeSystemContext)) { LESS -> Pair(exposedVisibility.toDescriptorVisibility(), userVisibility.toDescriptorVisibility()) else -> Pair(PRIVATE, PUBLIC) }