[FIR] Remove unneeded symbol.fir accesses

This commit is contained in:
Nikolay Lunyak
2024-01-11 14:32:37 +02:00
committed by Space Team
parent 965d8d2fd5
commit 95989fc3e2
19 changed files with 97 additions and 85 deletions
@@ -22,8 +22,9 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.isEnumEntries import org.jetbrains.kotlin.fir.isEnumEntries
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.js.common.RESERVED_KEYWORDS import org.jetbrains.kotlin.js.common.RESERVED_KEYWORDS
import org.jetbrains.kotlin.js.common.SPECIAL_KEYWORDS import org.jetbrains.kotlin.js.common.SPECIAL_KEYWORDS
@@ -73,7 +74,7 @@ object FirJsExportDeclarationChecker : FirBasicDeclarationChecker() {
checkTypeParameter(typeParameter) checkTypeParameter(typeParameter)
} }
if (declaration.isInlineWithReified) { if (declaration.symbol.isInlineWithReified) {
reportWrongExportedDeclaration("inline function with reified type parameters") reportWrongExportedDeclaration("inline function with reified type parameters")
return return
} }
@@ -153,13 +154,12 @@ object FirJsExportDeclarationChecker : FirBasicDeclarationChecker() {
return parent != null && parent.isInterface return parent != null && parent.isInterface
} }
private val FirCallableDeclaration.isInlineWithReified: Boolean private val FirCallableSymbol<*>.isInlineWithReified: Boolean
get() = when (this) { get() = when (this) {
is FirPropertyAccessor -> { is FirPropertyAccessorSymbol -> {
@OptIn(SymbolInternals::class) this.propertySymbol.isInlineWithReified
this.propertySymbol.fir.isInlineWithReified
} }
else -> typeParameters.any { it.symbol.isReified } else -> typeParameterSymbols.any { it.isReified }
} }
private fun ConeKotlinType.isExportableReturn(session: FirSession, currentlyProcessed: MutableSet<ConeKotlinType> = hashSetOf()) = private fun ConeKotlinType.isExportableReturn(session: FirSession, currentlyProcessed: MutableSet<ConeKotlinType> = hashSetOf()) =
@@ -208,8 +208,7 @@ object FirJsExportDeclarationChecker : FirBasicDeclarationChecker() {
return when { return when {
isPrimitiveExportableType -> true isPrimitiveExportableType -> true
@OptIn(SymbolInternals::class) symbol?.isMemberDeclaration != true -> false
symbol?.fir !is FirMemberDeclaration -> false
isEnum -> true isEnum -> true
else -> symbol.isEffectivelyExternal(session) || symbol.isExportedObject(session) else -> symbol.isEffectivelyExternal(session) || symbol.isExportedObject(session)
} }
@@ -8,8 +8,8 @@ package org.jetbrains.kotlin.fir.analysis.jvm
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.containingClassLookupTag import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
/** /**
* With JVM compilation * With JVM compilation
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement
* `kotlin.Throwable` does not require `override` keyword. * `kotlin.Throwable` does not require `override` keyword.
*/ */
object FirJvmOverridesBackwardCompatibilityHelper : FirOverridesBackwardCompatibilityHelper() { object FirJvmOverridesBackwardCompatibilityHelper : FirOverridesBackwardCompatibilityHelper() {
override fun additionalCheck(member: FirCallableDeclaration): Boolean? { override fun additionalCheck(member: FirCallableSymbol<*>): Boolean? {
if (!member.isJavaOrEnhancement) return false if (!member.isJavaOrEnhancement) return false
val containingClassName = member.containingClassLookupTag()?.classId?.asSingleFqName()?.toUnsafe() ?: return false val containingClassName = member.containingClassLookupTag()?.classId?.asSingleFqName()?.toUnsafe() ?: return false
// If the super class is mapped to a Kotlin built-in class, then we don't require `override` keyword. // If the super class is mapped to a Kotlin built-in class, then we don't require `override` keyword.
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.languageVersionSettings
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.types.coneType import org.jetbrains.kotlin.fir.types.coneType
@@ -212,10 +211,7 @@ object FirJvmStaticChecker : FirBasicDeclarationChecker() {
private fun CheckerContext.containerIsNonCompanionObject(outerLevel: Int): Boolean { private fun CheckerContext.containerIsNonCompanionObject(outerLevel: Int): Boolean {
val containingClassSymbol = this.getContainerAt(outerLevel) ?: return false val containingClassSymbol = this.getContainerAt(outerLevel) ?: return false
val containingClass = (containingClassSymbol as? FirRegularClassSymbol) ?: return false
@OptIn(SymbolInternals::class)
val containingClass = (containingClassSymbol.fir as? FirRegularClass) ?: return false
return containingClass.classKind == ClassKind.OBJECT && !containingClass.isCompanion return containingClass.classKind == ClassKind.OBJECT && !containingClass.isCompanion
} }
@@ -7,18 +7,17 @@ package org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
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.declaration.FirAbstractOverrideChecker import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirAbstractOverrideChecker
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.java.enhancement.EnhancedForWarningConeSubstitutor import org.jetbrains.kotlin.fir.java.enhancement.EnhancedForWarningConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.firOverrideChecker import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.typeContext import org.jetbrains.kotlin.fir.types.typeContext
@@ -41,22 +40,21 @@ object FirOverrideJavaNullabilityWarningChecker : FirAbstractOverrideChecker() {
val enhancedOverrides = scope val enhancedOverrides = scope
.getDirectOverriddenFunctions(member.symbol) .getDirectOverriddenFunctions(member.symbol)
.map { .map {
@OptIn(SymbolInternals::class) val substitutedBase = it.substituteOrNull(substitutor, context) ?: return@map it
val substitutedBase = it.fir.substituteOrNull(substitutor, context) ?: return@map it
anyBaseEnhanced = true anyBaseEnhanced = true
if (!anyReported && !context.session.firOverrideChecker.isOverriddenFunction(member, substitutedBase)) { if (!anyReported && !context.session.firOverrideChecker.isOverriddenFunction(member.symbol, substitutedBase)) {
anyReported = true anyReported = true
reporter.reportOn( reporter.reportOn(
member.source, member.source,
FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE, FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE,
member.symbol, member.symbol,
substitutedBase.symbol, substitutedBase,
context context
) )
} }
substitutedBase.symbol substitutedBase
} }
if (anyBaseEnhanced && !anyReported) { if (anyBaseEnhanced && !anyReported) {
@@ -70,22 +68,21 @@ object FirOverrideJavaNullabilityWarningChecker : FirAbstractOverrideChecker() {
val enhancedOverrides = scope val enhancedOverrides = scope
.getDirectOverriddenProperties(member.symbol) .getDirectOverriddenProperties(member.symbol)
.map { .map {
@OptIn(SymbolInternals::class) val substitutedBase = it.substituteOrNull(substitutor, context) ?: return@map it
val substitutedBase = it.fir.substituteOrNull(substitutor, context) ?: return@map it
anyBaseEnhanced = true anyBaseEnhanced = true
if (!anyReported && !context.session.firOverrideChecker.isOverriddenProperty(member, substitutedBase)) { if (!anyReported && !context.session.firOverrideChecker.isOverriddenProperty(member.symbol, substitutedBase)) {
anyReported = true anyReported = true
reporter.reportOn( reporter.reportOn(
member.source, member.source,
FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE, FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE,
member.symbol, member.symbol,
substitutedBase.symbol, substitutedBase,
context context
) )
} }
substitutedBase.symbol substitutedBase
} }
if (anyBaseEnhanced && !anyReported) { if (anyBaseEnhanced && !anyReported) {
@@ -133,6 +130,15 @@ private fun FirSimpleFunction.substituteOrNull(
} }
} }
private fun FirNamedFunctionSymbol.substituteOrNull(
substitutor: EnhancedForWarningConeSubstitutor,
context: CheckerContext,
): FirNamedFunctionSymbol? {
// Ok, because `substituteOrNull` calls lazyResolveToPhase
@OptIn(SymbolInternals::class)
return fir.substituteOrNull(substitutor, context)?.symbol
}
/** /**
* @see org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope.createSubstitutionOverrideProperty * @see org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope.createSubstitutionOverrideProperty
* @see org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope.createSubstitutedData * @see org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope.createSubstitutedData
@@ -163,4 +169,13 @@ private fun FirProperty.substituteOrNull(
newReceiverType = newExtensionReceiverType, newReceiverType = newExtensionReceiverType,
) )
} }
} }
private fun FirPropertySymbol.substituteOrNull(
substitutor: EnhancedForWarningConeSubstitutor,
context: CheckerContext,
): FirPropertySymbol? {
// Ok, because `substituteOrNull` calls `lazyResolveToPhase`
@OptIn(SymbolInternals::class)
return fir.substituteOrNull(substitutor, context)?.symbol
}
@@ -7,14 +7,12 @@ package org.jetbrains.kotlin.fir.analysis.wasm.checkers
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.FirAbstractWebCheckerUtils import org.jetbrains.kotlin.fir.analysis.web.common.checkers.FirAbstractWebCheckerUtils
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal
import org.jetbrains.kotlin.fir.declarations.utils.isInterface import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
object FirWasmWebCheckerUtils : FirAbstractWebCheckerUtils() { object FirWasmWebCheckerUtils : FirAbstractWebCheckerUtils() {
@OptIn(SymbolInternals::class)
override fun isNativeOrExternalInterface(symbol: FirBasedSymbol<*>, session: FirSession): Boolean = override fun isNativeOrExternalInterface(symbol: FirBasedSymbol<*>, session: FirSession): Boolean =
symbol.isEffectivelyExternal(session) && (symbol.fir as? FirClass)?.isInterface == true symbol.isEffectivelyExternal(session) && (symbol as? FirClassSymbol<*>)?.isInterface == true
} }
@@ -15,8 +15,9 @@ import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
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.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -54,16 +55,14 @@ abstract class FirOverridesBackwardCompatibilityHelper : FirSessionComponent {
val originalMemberSymbol = symbol.originalOrSelf() val originalMemberSymbol = symbol.originalOrSelf()
originalMemberSymbol.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) originalMemberSymbol.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
@OptIn(SymbolInternals::class) if (originalMemberSymbol.hasAnnotation(platformDependentAnnotation, context.session)) {
val originalMember = originalMemberSymbol.fir
if (originalMember.hasAnnotation(platformDependentAnnotation, context.session)) {
return true return true
} }
additionalCheck(originalMember)?.let { return it } additionalCheck(originalMemberSymbol)?.let { return it }
if (!originalMember.isAbstract) { if (!originalMemberSymbol.isAbstract) {
val containingClass = originalMember.containingClassLookupTag()?.toFirRegularClassSymbol(context.session) val containingClass = originalMemberSymbol.containingClassLookupTag()?.toFirRegularClassSymbol(context.session)
if (containingClass?.isInterface == false) { if (containingClass?.isInterface == false) {
return false return false
} }
@@ -71,16 +70,16 @@ abstract class FirOverridesBackwardCompatibilityHelper : FirSessionComponent {
val scope = val scope =
symbol.dispatchReceiverClassTypeOrNull()?.toRegularClassSymbol(context.session)?.unsubstitutedScope(context) ?: return false symbol.dispatchReceiverClassTypeOrNull()?.toRegularClassSymbol(context.session)?.unsubstitutedScope(context) ?: return false
val overriddenSymbols = when (originalMember) { val overriddenSymbols = when (originalMemberSymbol) {
is FirSimpleFunction -> scope.getDirectOverriddenFunctions(originalMember.symbol) is FirNamedFunctionSymbol -> scope.getDirectOverriddenFunctions(originalMemberSymbol)
is FirProperty -> scope.getDirectOverriddenProperties(originalMember.symbol) is FirPropertySymbol -> scope.getDirectOverriddenProperties(originalMemberSymbol)
else -> return false else -> return false
} }
if (overriddenSymbols.isEmpty()) return false if (overriddenSymbols.isEmpty()) return false
return overriddenSymbols.all { isPlatformSpecificSymbolThatCanBeImplicitlyOverridden(it, visitedSymbols, context) } return overriddenSymbols.all { isPlatformSpecificSymbolThatCanBeImplicitlyOverridden(it, visitedSymbols, context) }
} }
protected open fun additionalCheck(member: FirCallableDeclaration): Boolean? = null protected open fun additionalCheck(member: FirCallableSymbol<*>): Boolean? = null
} }
val FirSession.overridesBackwardCompatibilityHelper: FirOverridesBackwardCompatibilityHelper by FirSession.sessionComponentAccessor() val FirSession.overridesBackwardCompatibilityHelper: FirOverridesBackwardCompatibilityHelper by FirSession.sessionComponentAccessor()
@@ -85,7 +85,6 @@ fun PropertyInitializationInfoData.checkPropertyAccesses(
) )
} }
@OptIn(SymbolInternals::class)
private fun PropertyInitializationInfoData.checkPropertyAccesses( private fun PropertyInitializationInfoData.checkPropertyAccesses(
graph: ControlFlowGraph, graph: ControlFlowGraph,
properties: Set<FirPropertySymbol>, properties: Set<FirPropertySymbol>,
@@ -116,7 +115,7 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses(
node is VariableAssignmentNode -> { node is VariableAssignmentNode -> {
val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: continue val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: continue
if (!symbol.fir.isVal || node.fir.unwrapLValue()?.hasCorrectReceiver() != true || symbol !in properties) continue if (!symbol.isVal || node.fir.unwrapLValue()?.hasCorrectReceiver() != true || symbol !in properties) continue
if (getValue(node).values.any { it[symbol]?.canBeRevisited() == true }) { if (getValue(node).values.any { it[symbol]?.canBeRevisited() == true }) {
reporter.reportOn(node.fir.lValue.source, FirErrors.VAL_REASSIGNMENT, symbol, context) reporter.reportOn(node.fir.lValue.source, FirErrors.VAL_REASSIGNMENT, symbol, context)
@@ -518,15 +518,14 @@ private fun FirDeclarationCollector<*>.areNonConflictingCallables(
return session.declarationOverloadabilityHelper.isOverloadable(declaration, conflicting) return session.declarationOverloadabilityHelper.isOverloadable(declaration, conflicting)
} }
@OptIn(SymbolInternals::class) internal fun FirVariable.getDestructuredParameter(): FirValueParameterSymbol? {
internal fun FirVariable.getDestructuredParameter(): FirValueParameter? {
val initializer = initializer val initializer = initializer
if (initializer !is FirComponentCall) return null if (initializer !is FirComponentCall) return null
if (initializer.source?.kind !is KtFakeSourceElementKind.DesugaredComponentFunctionCall) return null if (initializer.source?.kind !is KtFakeSourceElementKind.DesugaredComponentFunctionCall) return null
val receiver = initializer.dispatchReceiver ?: initializer.extensionReceiver ?: return null val receiver = initializer.dispatchReceiver ?: initializer.extensionReceiver ?: return null
if (receiver !is FirPropertyAccessExpression) return null if (receiver !is FirPropertyAccessExpression) return null
val calleeReference = receiver.calleeReference as? FirResolvedNamedReference ?: return null val calleeReference = receiver.calleeReference as? FirResolvedNamedReference ?: return null
return calleeReference.resolvedSymbol.fir as? FirValueParameter return calleeReference.resolvedSymbol as? FirValueParameterSymbol
} }
/** Checks for redeclarations of value and type parameters, and local variables. */ /** Checks for redeclarations of value and type parameters, and local variables. */
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.hasAnnotation import org.jetbrains.kotlin.fir.declarations.hasAnnotation
import org.jetbrains.kotlin.fir.declarations.utils.isConst import org.jetbrains.kotlin.fir.declarations.utils.isConst
import org.jetbrains.kotlin.fir.declarations.utils.isStatic import org.jetbrains.kotlin.fir.declarations.utils.isStatic
@@ -194,19 +193,19 @@ internal fun checkConstantArguments(
val propertySymbol = expressionSymbol as? FirPropertySymbol ?: return ConstantArgumentKind.NOT_CONST val propertySymbol = expressionSymbol as? FirPropertySymbol ?: return ConstantArgumentKind.NOT_CONST
@OptIn(SymbolInternals::class)
val property = propertySymbol.fir
when { when {
property.unwrapFakeOverrides().symbol.canBeEvaluated() || property.isCompileTimeBuiltinProperty(session) -> { propertySymbol.unwrapFakeOverrides().canBeEvaluated() || propertySymbol.isCompileTimeBuiltinProperty(session) -> {
val receiver = listOf(expression.dispatchReceiver, expression.extensionReceiver).single { it != null }!! val receiver = listOf(expression.dispatchReceiver, expression.extensionReceiver).single { it != null }!!
return checkConstantArguments(receiver, session) return checkConstantArguments(receiver, session)
} }
propertySymbol.isLocal -> return ConstantArgumentKind.NOT_CONST propertySymbol.isLocal -> return ConstantArgumentKind.NOT_CONST
expressionType.classId == StandardClassIds.KClass -> return ConstantArgumentKind.NOT_KCLASS_LITERAL expressionType.classId == StandardClassIds.KClass -> return ConstantArgumentKind.NOT_KCLASS_LITERAL
} }
return when (property.initializer) { // Ok, because we only look at the structure, not resolution-dependent properties.
@OptIn(SymbolInternals::class)
return when (propertySymbol.fir.initializer) {
is FirConstExpression<*> -> when { is FirConstExpression<*> -> when {
property.isVal -> ConstantArgumentKind.NOT_CONST_VAL_IN_CONST_EXPRESSION propertySymbol.isVal -> ConstantArgumentKind.NOT_CONST_VAL_IN_CONST_EXPRESSION
else -> ConstantArgumentKind.NOT_CONST else -> ConstantArgumentKind.NOT_CONST
} }
is FirGetClassCall -> ConstantArgumentKind.NOT_KCLASS_LITERAL is FirGetClassCall -> ConstantArgumentKind.NOT_KCLASS_LITERAL
@@ -255,7 +254,7 @@ private fun FirFunctionCall.isCompileTimeBuiltinCall(session: FirSession): Boole
return false return false
} }
private fun FirProperty.isCompileTimeBuiltinProperty(session: FirSession): Boolean { private fun FirPropertySymbol.isCompileTimeBuiltinProperty(session: FirSession): Boolean {
val receiverType = dispatchReceiverType ?: receiverParameter?.typeRef?.coneTypeSafe<ConeKotlinType>() ?: return false val receiverType = dispatchReceiverType ?: receiverParameter?.typeRef?.coneTypeSafe<ConeKotlinType>() ?: return false
val receiverClassId = receiverType.fullyExpandedClassId(session) ?: return false val receiverClassId = receiverType.fullyExpandedClassId(session) ?: return false
return when (name.asString()) { return when (name.asString()) {
@@ -345,13 +345,11 @@ fun FirCallableSymbol<*>.getImplementationStatus(
var hasImplementationVar = false var hasImplementationVar = false
for (intersection in symbol.intersections) { for (intersection in symbol.intersections) {
@OptIn(SymbolInternals::class) val unwrapped = intersection.unwrapFakeOverrides()
val fir = intersection.fir val isVar = unwrapped is FirPropertySymbol && unwrapped.isVar
val unwrappedFir = fir.unwrapFakeOverrides() val isFromClass = unwrapped.getContainingClassSymbol(sessionHolder.session)?.classKind == ClassKind.CLASS
val isVar = unwrappedFir is FirProperty && unwrappedFir.isVar
val isFromClass = unwrappedFir.getContainingClassSymbol(sessionHolder.session)?.classKind == ClassKind.CLASS
if (fir.isAbstract) { if (intersection.isAbstract) {
if (isFromClass) { if (isFromClass) {
hasAbstractFromClass = true hasAbstractFromClass = true
} }
@@ -359,7 +357,7 @@ fun FirCallableSymbol<*>.getImplementationStatus(
hasAbstractVar = true hasAbstractVar = true
} }
} else { } else {
if (fir.origin == FirDeclarationOrigin.Delegated) { if (intersection.origin == FirDeclarationOrigin.Delegated) {
hasInterfaceDelegation = true hasInterfaceDelegation = true
} }
if (isFromClass) { if (isFromClass) {
@@ -53,7 +53,9 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
private fun getDestructuredParameters(function: FirFunction): List<FirVariable> { private fun getDestructuredParameters(function: FirFunction): List<FirVariable> {
if (function.valueParameters.none { it.name == SpecialNames.DESTRUCT }) return function.valueParameters if (function.valueParameters.none { it.name == SpecialNames.DESTRUCT }) return function.valueParameters
val destructuredParametersBoxes = function.valueParameters.filterTo(mutableSetOf()) { it.name == SpecialNames.DESTRUCT } val destructuredParametersBoxes = function.valueParameters
.filter { it.name == SpecialNames.DESTRUCT }
.mapTo(mutableSetOf()) { it.symbol }
return function.body?.statements.orEmpty().mapNotNullTo(function.valueParameters.toMutableList()) { return function.body?.statements.orEmpty().mapNotNullTo(function.valueParameters.toMutableList()) {
val destructuredParameter = (it as? FirVariable)?.getDestructuredParameter() ?: return@mapNotNullTo null val destructuredParameter = (it as? FirVariable)?.getDestructuredParameter() ?: return@mapNotNullTo null
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.toResolvedValueParameterSymbol import org.jetbrains.kotlin.fir.references.toResolvedValueParameterSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
@@ -97,8 +96,7 @@ object FirFunctionParameterChecker : FirFunctionChecker() {
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) { override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
val referredParameter = qualifiedAccessExpression.calleeReference.toResolvedValueParameterSymbol() ?: return val referredParameter = qualifiedAccessExpression.calleeReference.toResolvedValueParameterSymbol() ?: return
@OptIn(SymbolInternals::class) val referredParameterIndex = function.valueParameters.indexOfFirst { it.symbol == referredParameter }
val referredParameterIndex = function.valueParameters.indexOf(referredParameter.fir)
// Skip if the referred parameter is not declared in the same function. // Skip if the referred parameter is not declared in the same function.
if (referredParameterIndex < 0) return if (referredParameterIndex < 0) return
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDeprecated import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDeprecated
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
object FirDeprecatedQualifierChecker : FirResolvedQualifierChecker() { object FirDeprecatedQualifierChecker : FirResolvedQualifierChecker() {
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -27,8 +26,7 @@ object FirDeprecatedQualifierChecker : FirResolvedQualifierChecker() {
// is handled automatically when getting deprecationInfo // is handled automatically when getting deprecationInfo
// for the typealias symbol (in FirDeprecationChecker). // for the typealias symbol (in FirDeprecationChecker).
// Below we check "the last transition". // Below we check "the last transition".
@OptIn(SymbolInternals::class) val companionSymbol = expression.symbol?.fullyExpandedClass(context.session)?.companionObjectSymbol ?: return
val companionSymbol = expression.symbol?.fullyExpandedClass(context.session)?.fir?.companionObjectSymbol ?: return
FirDeprecationChecker.reportApiStatusIfNeeded(expression.source, companionSymbol, context, reporter) FirDeprecationChecker.reportApiStatusIfNeeded(expression.source, companionSymbol, context, reporter)
} }
} }
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.utils.sourceElement import org.jetbrains.kotlin.fir.declarations.utils.sourceElement
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
@@ -34,8 +33,7 @@ object FirIncompatibleClassExpressionChecker : FirQualifiedAccessExpressionCheck
} }
} }
@OptIn(SymbolInternals::class) checkSourceElement(symbol.containerSource, expression, context, reporter)
checkSourceElement(symbol.fir.containerSource, expression, context, reporter)
} }
internal fun checkType(type: ConeKotlinType?, element: FirElement, context: CheckerContext, reporter: DiagnosticReporter) { internal fun checkType(type: ConeKotlinType?, element: FirElement, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.diagnostics.reportOn
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.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.hasAnnotation import org.jetbrains.kotlin.fir.declarations.hasAnnotation
import org.jetbrains.kotlin.fir.declarations.utils.isInline import org.jetbrains.kotlin.fir.declarations.utils.isInline
@@ -19,7 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.name.StandardClassIds.Annotations import org.jetbrains.kotlin.name.StandardClassIds.Annotations
@@ -51,7 +50,8 @@ object FirLateinitIntrinsicApplicabilityChecker : FirQualifiedAccessExpressionCh
} }
// property must be declared in one of the outer lexical scopes // property must be declared in one of the outer lexical scopes
if (calleePropertySymbol.containingClassOrFile(context) !in context.containingDeclarations) { val containingSymbol = calleePropertySymbol.containingClassOrFile(context)
if (context.containingDeclarations.none { it.symbol == containingSymbol }) {
reporter.reportOn( reporter.reportOn(
source, source,
FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY, FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY,
@@ -70,11 +70,10 @@ object FirLateinitIntrinsicApplicabilityChecker : FirQualifiedAccessExpressionCh
/** /**
* Returns the containing class or file if the property is top-level. * Returns the containing class or file if the property is top-level.
*/ */
@OptIn(SymbolInternals::class)
private fun FirPropertySymbol.containingClassOrFile( private fun FirPropertySymbol.containingClassOrFile(
context: CheckerContext context: CheckerContext
): FirDeclaration? { ): FirBasedSymbol<*>? {
return getContainingClassSymbol(context.session)?.fir return getContainingClassSymbol(context.session)
?: context.session.firProvider.getFirCallableContainerFile(this) ?: context.session.firProvider.getFirCallableContainerFile(this)?.symbol
} }
} }
@@ -150,9 +150,8 @@ object FirOptInUsageBaseChecker {
fromSetter = false, dispatchReceiverType = null, fromSupertype = true fromSetter = false, dispatchReceiverType = null, fromSupertype = true
) )
@OptIn(SymbolInternals::class)
fun FirClassLikeSymbol<*>.isExperimentalMarker(session: FirSession) = fun FirClassLikeSymbol<*>.isExperimentalMarker(session: FirSession) =
this is FirRegularClassSymbol && fir.getAnnotationByClassId(OptInNames.REQUIRES_OPT_IN_CLASS_ID, session) != null this is FirRegularClassSymbol && getAnnotationByClassId(OptInNames.REQUIRES_OPT_IN_CLASS_ID, session) != null
@OptIn(SymbolInternals::class) @OptIn(SymbolInternals::class)
private fun FirBasedSymbol<*>.loadExperimentalities( private fun FirBasedSymbol<*>.loadExperimentalities(
@@ -284,7 +283,7 @@ object FirOptInUsageBaseChecker {
else -> null else -> null
} }
val severity = Experimentality.Severity.values().firstOrNull { it.name == levelName } ?: Experimentality.DEFAULT_SEVERITY val severity = Experimentality.Severity.entries.firstOrNull { it.name == levelName } ?: Experimentality.DEFAULT_SEVERITY
val message = (experimental.findArgumentByName(MESSAGE) as? FirConstExpression<*>)?.value as? String val message = (experimental.findArgumentByName(MESSAGE) as? FirConstExpression<*>)?.value as? String
return Experimentality(symbol.classId, severity, message, annotatedOwnerClassName) return Experimentality(symbol.classId, severity, message, annotatedOwnerClassName)
} }
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
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.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.FirPropertySymbol
interface FirOverrideChecker : FirSessionComponent { interface FirOverrideChecker : FirSessionComponent {
fun isOverriddenFunction( fun isOverriddenFunction(
@@ -29,4 +31,9 @@ fun FirOverrideChecker.isOverriddenFunction(
baseDeclaration: FirNamedFunctionSymbol baseDeclaration: FirNamedFunctionSymbol
): Boolean = isOverriddenFunction(overrideCandidate.fir, baseDeclaration.fir) ): Boolean = isOverriddenFunction(overrideCandidate.fir, baseDeclaration.fir)
fun FirOverrideChecker.isOverriddenProperty(
overrideCandidate: FirCallableSymbol<*>,
baseDeclaration: FirPropertySymbol
): Boolean = isOverriddenProperty(overrideCandidate.fir, baseDeclaration.fir)
val FirSession.firOverrideChecker: FirOverrideChecker by FirSession.sessionComponentAccessor() val FirSession.firOverrideChecker: FirOverrideChecker by FirSession.sessionComponentAccessor()
@@ -50,6 +50,10 @@ val FirDeclaration.isNonLocal
val FirCallableDeclaration.isExtension get() = receiverParameter != null val FirCallableDeclaration.isExtension get() = receiverParameter != null
val FirBasedSymbol<*>.isMemberDeclaration: Boolean
// Accessing `fir` is ok, because we don't really use it
get() = fir is FirMemberDeclaration
val FirBasedSymbol<*>.memberDeclarationNameOrNull: Name? val FirBasedSymbol<*>.memberDeclarationNameOrNull: Name?
// Accessing `fir` is ok, because `nameOrSpecialName` only accesses names // Accessing `fir` is ok, because `nameOrSpecialName` only accesses names
get() = (fir as? FirMemberDeclaration)?.nameOrSpecialName get() = (fir as? FirMemberDeclaration)?.nameOrSpecialName
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.mpp.CallableSymbolMarker import org.jetbrains.kotlin.mpp.CallableSymbolMarker
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
abstract class FirCallableSymbol<D : FirCallableDeclaration> : FirBasedSymbol<D>(), CallableSymbolMarker { abstract class FirCallableSymbol<D : FirCallableDeclaration> : FirBasedSymbol<D>(), CallableSymbolMarker {
abstract val callableId: CallableId abstract val callableId: CallableId
@@ -76,6 +77,10 @@ abstract class FirCallableSymbol<D : FirCallableDeclaration> : FirBasedSymbol<D>
val name: Name val name: Name
get() = callableId.callableName get() = callableId.callableName
val containerSource: DeserializedContainerSource?
// This is ok, because containerSource should be set during fir creation
get() = fir.containerSource
fun getDeprecation(languageVersionSettings: LanguageVersionSettings): DeprecationsPerUseSite? { fun getDeprecation(languageVersionSettings: LanguageVersionSettings): DeprecationsPerUseSite? {
lazyResolveToPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) lazyResolveToPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
return fir.deprecationsProvider.getDeprecationsInfo(languageVersionSettings) return fir.deprecationsProvider.getDeprecationsInfo(languageVersionSettings)