[FIR] Review symbol.fir in FirVisibilityQualifierChecker

Also introduce `firForVisibilityChecker`.
This way it's easier to use compared to
defining overloads in `FirVisibilityChecker`
that accept symbols.

This change exists, because I wasn't able
to make myself sure that accessing fir here
is safe. We may come here after a typealias
expansion, after all.
This commit is contained in:
Nikolay Lunyak
2024-01-12 13:21:55 +02:00
committed by Space Team
parent 0b7e8c4708
commit cb89695e21
2 changed files with 22 additions and 11 deletions
@@ -10,17 +10,18 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isStandalone import org.jetbrains.kotlin.fir.analysis.checkers.isStandalone
import org.jetbrains.kotlin.fir.analysis.diagnostics.toInvisibleReferenceDiagnostic import org.jetbrains.kotlin.fir.analysis.diagnostics.toInvisibleReferenceDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.expressions.FirErrorResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirErrorResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.firForVisibilityChecker
import org.jetbrains.kotlin.fir.getOwnerLookupTag import org.jetbrains.kotlin.fir.getOwnerLookupTag
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeVisibilityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeVisibilityError
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.toSymbol import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.fir.visibilityChecker import org.jetbrains.kotlin.fir.visibilityChecker
@@ -29,7 +30,6 @@ object FirVisibilityQualifierChecker : FirResolvedQualifierChecker() {
checkClassLikeSymbol(expression.symbol ?: return, expression, expression.isStandalone(context), context, reporter) checkClassLikeSymbol(expression.symbol ?: return, expression, expression.isStandalone(context), context, reporter)
} }
@OptIn(SymbolInternals::class)
private fun checkClassLikeSymbol( private fun checkClassLikeSymbol(
symbol: FirClassLikeSymbol<*>, symbol: FirClassLikeSymbol<*>,
expression: FirResolvedQualifier, expression: FirResolvedQualifier,
@@ -38,13 +38,13 @@ object FirVisibilityQualifierChecker : FirResolvedQualifierChecker() {
reporter: DiagnosticReporter, reporter: DiagnosticReporter,
) { ) {
val firFile = context.containingFile ?: return val firFile = context.containingFile ?: return
val firClassLikeDeclaration = symbol.fir
// Note: errors on implicit receiver are already reported in coneDiagnosticToFirDiagnostic // Note: errors on implicit receiver are already reported in coneDiagnosticToFirDiagnostic
// See e.g. diagnostics/tests/visibility/packagePrivateStaticViaInternal.fir.kt // See e.g. diagnostics/tests/visibility/packagePrivateStaticViaInternal.fir.kt
if (expression.source?.kind != KtFakeSourceElementKind.ImplicitReceiver && if (expression.source?.kind != KtFakeSourceElementKind.ImplicitReceiver &&
!context.session.visibilityChecker.isClassLikeVisible( !context.session.visibilityChecker.isClassLikeVisible(
firClassLikeDeclaration, context.session, firFile, context.containingDeclarations, symbol.firForVisibilityChecker,
context.session, firFile, context.containingDeclarations,
) )
) { ) {
if (expression !is FirErrorResolvedQualifier || expression.diagnostic !is ConeVisibilityError) { if (expression !is FirErrorResolvedQualifier || expression.diagnostic !is ConeVisibilityError) {
@@ -67,8 +67,8 @@ object FirVisibilityQualifierChecker : FirResolvedQualifierChecker() {
} }
} }
if (firClassLikeDeclaration is FirTypeAlias) { if (symbol is FirTypeAliasSymbol) {
firClassLikeDeclaration.expandedConeType?.toSymbol(context.session)?.let { symbol.resolvedExpandedTypeRef.coneTypeSafe<ConeClassLikeType>()?.toSymbol(context.session)?.let {
checkClassLikeSymbol(it, expression, isStandalone, context, reporter) checkClassLikeSymbol(it, expression, isStandalone, context, reporter)
} }
} }
@@ -78,11 +78,12 @@ object FirVisibilityQualifierChecker : FirResolvedQualifierChecker() {
} }
} }
@OptIn(SymbolInternals::class)
private fun FirRegularClassSymbol.toInvisibleCompanion(context: CheckerContext): FirRegularClassSymbol? { private fun FirRegularClassSymbol.toInvisibleCompanion(context: CheckerContext): FirRegularClassSymbol? {
val firFile = context.containingFile ?: return null val firFile = context.containingFile ?: return null
return companionObjectSymbol?.takeIf { return companionObjectSymbol?.takeIf {
!context.session.visibilityChecker.isClassLikeVisible(it.fir, context.session, firFile, context.containingDeclarations) !context.session.visibilityChecker.isClassLikeVisible(
it.firForVisibilityChecker, context.session, firFile, context.containingDeclarations,
)
} }
} }
} }
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -546,3 +547,12 @@ private fun FirClassLikeDeclaration.containingNonLocalClass(session: FirSession)
is FirTypeAlias -> null is FirTypeAlias -> null
} }
} }
/**
* The returned fir can be passed to the visibility checker, but don't
* use it for anything else.
*/
val <D, S : FirBasedSymbol<out D>> S.firForVisibilityChecker: D
get() = fir.also {
lazyResolveToPhase(FirResolvePhase.STATUS)
}