diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt index 6b923bce006..960a321862e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isFunctionalType import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.resolve.transformers.publishedApiEffectiveVisibility import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol @@ -196,7 +197,8 @@ object FirInlineDeclarationChecker : FirMemberDeclarationChecker() { context: CheckerContext ) { if (calledDeclaration == null) return - val calledFunEffectiveVisibility = calledDeclaration.effectiveVisibility.let { + val recordedEffectiveVisibility = calledDeclaration.publishedApiEffectiveVisibility ?: calledDeclaration.effectiveVisibility + val calledFunEffectiveVisibility = recordedEffectiveVisibility.let { if (it == EffectiveVisibility.Local) { EffectiveVisibility.Public } else { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt index 70d5e42c777..cd2539947e3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt @@ -22,16 +22,16 @@ fun Visibility.toEffectiveVisibility( fun Visibility.toEffectiveVisibility( owner: ConeClassLikeLookupTag?, forClass: Boolean = false, - checkPublishedApi: Boolean = false + ownerIsPublishedApi: Boolean = false ): EffectiveVisibility { customEffectiveVisibility()?.let { return it } return when (this.normalize()) { Visibilities.PrivateToThis, Visibilities.InvisibleFake -> EffectiveVisibility.PrivateInClass Visibilities.Private -> if (owner == null && forClass) EffectiveVisibility.PrivateInFile else EffectiveVisibility.PrivateInClass Visibilities.Protected -> EffectiveVisibility.Protected(owner) - Visibilities.Internal -> when (!checkPublishedApi /*|| !owner.isPublishedApi()*/) { // TODO - true -> EffectiveVisibility.Internal - false -> EffectiveVisibility.Public + Visibilities.Internal -> when (ownerIsPublishedApi) { + true -> EffectiveVisibility.Public + false -> EffectiveVisibility.Internal } Visibilities.Public -> EffectiveVisibility.Public Visibilities.Local -> EffectiveVisibility.Local diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt index 96feef467bd..c841015715b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt @@ -16,6 +16,9 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.toEffectiveVisibility import org.jetbrains.kotlin.fir.typeContext +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.coneTypeSafe +import org.jetbrains.kotlin.name.StandardClassIds class FirStatusResolver( val session: FirSession, @@ -172,6 +175,22 @@ class FirStatusResolver( containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*> ) val effectiveVisibility = parentEffectiveVisibility.lowerBound(selfEffectiveVisibility, session.typeContext) + val annotations = ((containingProperty ?: declaration) as? FirAnnotatedDeclaration)?.annotations ?: emptyList() + if (annotations.any { it.typeRef.coneTypeSafe()?.lookupTag?.classId == StandardClassIds.PublishedApi }) { + val publishedApiSelfEffectiveVisibility = visibility.toEffectiveVisibility( + containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*>, ownerIsPublishedApi = true + ) + val parentPublishedEffectiveVisibility = when { + containingProperty != null -> containingProperty.publishedApiEffectiveVisibility + containingClass is FirRegularClass -> containingClass.publishedApiEffectiveVisibility + else -> null + } ?: parentEffectiveVisibility + declaration.publishedApiEffectiveVisibility = parentPublishedEffectiveVisibility.lowerBound( + publishedApiSelfEffectiveVisibility, + session.typeContext + ) + } + return status.resolved(visibility, modality, effectiveVisibility) } @@ -243,3 +262,6 @@ private fun FirDeclaration.hasOwnBodyOrAccessorBody(): Boolean { else -> true } } + +private object PublishedApiEffectiveVisibilityKey : FirDeclarationDataKey() +var FirDeclaration.publishedApiEffectiveVisibility: EffectiveVisibility? by FirDeclarationDataRegistry.data(PublishedApiEffectiveVisibilityKey) diff --git a/compiler/testData/codegen/box/publishedApi/noMangling.kt b/compiler/testData/codegen/box/publishedApi/noMangling.kt index d330db2bc84..1aa6627b831 100644 --- a/compiler/testData/codegen/box/publishedApi/noMangling.kt +++ b/compiler/testData/codegen/box/publishedApi/noMangling.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM //WITH_REFLECT class A { diff --git a/compiler/testData/codegen/box/publishedApi/simple.kt b/compiler/testData/codegen/box/publishedApi/simple.kt index b6868dd3c59..f04288e21bb 100644 --- a/compiler/testData/codegen/box/publishedApi/simple.kt +++ b/compiler/testData/codegen/box/publishedApi/simple.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // MODULE: lib // FILE: lib.kt class A { diff --git a/compiler/testData/codegen/box/publishedApi/topLevel.kt b/compiler/testData/codegen/box/publishedApi/topLevel.kt index 45614c81b72..901254d4f05 100644 --- a/compiler/testData/codegen/box/publishedApi/topLevel.kt +++ b/compiler/testData/codegen/box/publishedApi/topLevel.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // MODULE: lib // FILE: lib.kt @PublishedApi diff --git a/compiler/testData/diagnostics/tests/inline/publishedApi.fir.kt b/compiler/testData/diagnostics/tests/inline/publishedApi.fir.kt index 333587f6213..ba28cd7abd9 100644 --- a/compiler/testData/diagnostics/tests/inline/publishedApi.fir.kt +++ b/compiler/testData/diagnostics/tests/inline/publishedApi.fir.kt @@ -1,13 +1,13 @@ // !DIAGNOSTICS: -EXPOSED_PARAMETER_TYPE -NOTHING_TO_INLINE inline fun call(a: A) { - a.test() - publishedTopLevel() + a.test() + publishedTopLevel() - a.publishedVar - a.publishedVar = 1 + a.publishedVar + a.publishedVar = 1 - publishedVarTopLevel - publishedVarTopLevel = 1 + publishedVarTopLevel + publishedVarTopLevel = 1 } inline var inlineVar: Int diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt index 971dee70f61..7d361c39708 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt @@ -110,6 +110,8 @@ object StandardClassIds { val FlexibleNullability = ClassId(FqName("kotlin.internal.ir"), Name.identifier("FlexibleNullability")) val EnhancedNullability = ClassId(FqName("kotlin.jvm.internal"), Name.identifier("EnhancedNullability")) + + val PublishedApi = "PublishedApi".baseId() } private fun Map.inverseMap() = entries.associate { (k, v) -> v to k }