[FIR] Report all Visibilities.Unknown in FirOverrideChecker

Check all members for `Visibility.Unknown`,
otherwise we miss them when they come
from supertypes. This is the reason why
the FP intellij build failed with a
cryptic stacktrace instead of a
human-readable diagnostic.

Also, do report the diagnostic at all
cases of `Visibilities.Unknown`. Turns
out, there are no "simple to reason
about" situations here :(

Also, an interesting detail:
`retrieveDirectOverriddenOf` returns an
empty list for intersection overrides.
But this doesn't seem to break anything...

Replacing `CANNOT_INFER_VISIBILITY`'s
type `KtDeclaration` with
`PsiNameIdentifierOwner` and the related
changes in `PositioningStrategies`
were needed to prevent an exception saying that
`PsiClassImpl` is not a subtype of
`KtDeclaration`.
This commit is contained in:
Nikolay Lunyak
2024-02-20 14:20:22 +02:00
committed by Space Team
parent 053eb07692
commit 76ed5453b3
27 changed files with 149 additions and 46 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
@@ -926,7 +927,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<FirCallableSymbol<*>>("overridden")
parameter<Name>("containingClassName")
}
val CANNOT_INFER_VISIBILITY by error<KtDeclaration>(PositioningStrategy.DECLARATION_NAME) {
val CANNOT_INFER_VISIBILITY by error<PsiNameIdentifierOwner>(PositioningStrategy.DECLARATION_NAME) {
parameter<FirCallableSymbol<*>>("callable")
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
@@ -518,7 +519,7 @@ object FirErrors {
val DATA_CLASS_OVERRIDE_DEFAULT_VALUES: KtDiagnosticFactory2<FirCallableSymbol<*>, FirClassSymbol<*>> by error2<KtElement, FirCallableSymbol<*>, FirClassSymbol<*>>(SourceElementPositioningStrategies.DATA_MODIFIER)
val CANNOT_WEAKEN_ACCESS_PRIVILEGE: KtDiagnosticFactory3<Visibility, FirCallableSymbol<*>, Name> by error3<KtModifierListOwner, Visibility, FirCallableSymbol<*>, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val CANNOT_CHANGE_ACCESS_PRIVILEGE: KtDiagnosticFactory3<Visibility, FirCallableSymbol<*>, Name> by error3<KtModifierListOwner, Visibility, FirCallableSymbol<*>, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val CANNOT_INFER_VISIBILITY: KtDiagnosticFactory1<FirCallableSymbol<*>> by error1<KtDeclaration, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val CANNOT_INFER_VISIBILITY: KtDiagnosticFactory1<FirCallableSymbol<*>> by error1<PsiNameIdentifierOwner, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES: KtDiagnosticFactory3<Name, FirValueParameterSymbol, List<FirCallableSymbol<*>>> by error3<KtElement, Name, FirValueParameterSymbol, List<FirCallableSymbol<*>>>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE: KtDiagnosticFactory3<Name, FirValueParameterSymbol, List<FirCallableSymbol<*>>> by error3<KtElement, Name, FirValueParameterSymbol, List<FirCallableSymbol<*>>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_DEPRECATION: KtDiagnosticFactoryForDeprecation3<Name, FirValueParameterSymbol, List<FirCallableSymbol<*>>> by deprecationError3<KtElement, Name, FirValueParameterSymbol, List<FirCallableSymbol<*>>>(ProhibitAllMultipleDefaultsInheritedFromSupertypes, SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -141,17 +142,31 @@ sealed class FirOverrideChecker(mppKind: MppCheckerKind) : FirAbstractOverrideCh
// Other kinds of fake overrides may also be incorrect, but not to that extent, so we can
// check them more granularly. See the relevant comments.
firTypeScope.processAllProperties {
if (it.containingClassLookupTag() == declaration.symbol.toLookupTag() && !it.isSubstitutionOverride) {
fun checkMember(it: FirCallableSymbol<*>) {
val isFromThis = it.containingClassLookupTag() == declaration.symbol.toLookupTag()
if (isFromThis && !it.isSubstitutionOverride) {
checkMember(it, declaration, reporter, typeCheckerState, firTypeScope, context)
} else {
val source = it.source?.takeIf { isFromThis } ?: declaration.source
it.ensureKnownVisibility(context, reporter, source)
}
}
firTypeScope.processAllFunctions {
if (it.containingClassLookupTag() == declaration.symbol.toLookupTag() && !it.isSubstitutionOverride) {
checkMember(it, declaration, reporter, typeCheckerState, firTypeScope, context)
}
}
firTypeScope.processAllProperties(::checkMember)
firTypeScope.processAllFunctions(::checkMember)
}
/**
* Returns `false` if [Visibilities.Unknown].
*/
private fun FirCallableSymbol<*>.ensureKnownVisibility(
context: CheckerContext,
reporter: DiagnosticReporter,
source: KtSourceElement? = this.source,
) = when {
visibility != Visibilities.Unknown -> true
else -> false.also { reporter.reportOn(source, FirErrors.CANNOT_INFER_VISIBILITY, this, context) }
}
private fun checkModality(
@@ -178,13 +193,7 @@ sealed class FirOverrideChecker(mppKind: MppCheckerKind) : FirAbstractOverrideCh
overriddenSymbols: List<FirCallableSymbol<*>>,
context: CheckerContext
) {
if (visibility == Visibilities.Unknown) {
// MANY_*_NOT_IMPLEMENTED implies CANNOT_INFER_VISIBILITY as per KT-63741
val isManyNotImplementedDiagnosticReported = overriddenSymbols.count { !it.isAbstract } != 1
val isSimpleToReasonAboutSituation = overriddenSymbols.none { it.isIntersectionOverride }
if (!(isManyNotImplementedDiagnosticReported && isSimpleToReasonAboutSituation)) {
reporter.reportOn(source, FirErrors.CANNOT_INFER_VISIBILITY, this, context)
}
if (!ensureKnownVisibility(context, reporter)) {
return
}