diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirMissingDependencySupertypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirMissingDependencySupertypeChecker.kt index dc7f37ad86e..fbe18136ffc 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirMissingDependencySupertypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirMissingDependencySupertypeChecker.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn -import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.collectUpperBounds import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker @@ -36,13 +35,13 @@ object FirMissingDependencySupertypeChecker { object ForDeclarations : FirBasicDeclarationChecker() { override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration is FirClass) { - checkSupertypes(declaration.symbol, declaration.source, reporter, context) + checkSuperTypes(declaration.symbol, declaration.source, reporter, context) } if (declaration is FirTypeParameterRefsOwner) { for (typeParameter in declaration.typeParameters) { for (upperBound in typeParameter.toConeType().collectUpperBounds()) { - checkSupertypes(upperBound, typeParameter.source, reporter, context) + checkSuperTypes(upperBound, typeParameter.source, reporter, context) } } } @@ -57,30 +56,30 @@ object FirMissingDependencySupertypeChecker { if (symbol == null) { val receiverType = expression.explicitReceiver?.resolvedType ?.lowerBoundIfFlexible()?.originalIfDefinitelyNotNullable()?.fullyExpandedType(context.session) - checkSupertypes(receiverType, source, reporter, context) + checkSuperTypes(receiverType, source, reporter, context) return } - val missingSupertype = checkSupertypes(symbol.dispatchReceiverType, source, reporter, context) + val missingSupertype = checkSuperTypes(symbol.dispatchReceiverType, source, reporter, context) val eagerChecksAllowed = context.languageVersionSettings.getFlag(AnalysisFlags.extendedCompilerChecks) val unresolvedLazySupertypesByDefault = symbol is FirConstructorSymbol || symbol is FirAnonymousFunctionSymbol if (eagerChecksAllowed || !unresolvedLazySupertypesByDefault && !missingSupertype) { - checkSupertypes(symbol.getOwnerLookupTag()?.toSymbol(context.session), source, reporter, context) - checkSupertypes(symbol.resolvedReceiverTypeRef?.coneTypeOrNull, source, reporter, context) + checkSuperTypes(symbol.getOwnerLookupTag()?.toSymbol(context.session), source, reporter, context) + checkSuperTypes(symbol.resolvedReceiverTypeRef?.coneTypeOrNull, source, reporter, context) } } } - fun checkSupertypes( + fun checkSuperTypes( classifierType: ConeKotlinType?, source: KtSourceElement?, reporter: DiagnosticReporter, context: CheckerContext, - ): Boolean = checkSupertypes(classifierType?.toSymbol(context.session), source, reporter, context) + ): Boolean = checkSuperTypes(classifierType?.toSymbol(context.session), source, reporter, context) - fun checkSupertypes( + fun checkSuperTypes( declaration: FirBasedSymbol<*>?, source: KtSourceElement?, reporter: DiagnosticReporter, @@ -88,38 +87,17 @@ object FirMissingDependencySupertypeChecker { ): Boolean { if (declaration !is FirClassSymbol<*>) return false - var missingSupertype = false - val superTypes = declaration.collectSuperTypes(context.session) - for (superType in superTypes) { - if (superType is ConeErrorType || superType is ConeDynamicType) continue // Ignore types which are already errors. - - val superTypeSymbol = superType.toSymbol(context.session) - if (superTypeSymbol == null) { - missingSupertype = true - - reporter.reportOn( - source, - FirErrors.MISSING_DEPENDENCY_SUPERCLASS, - superType.withArguments(emptyArray()).withNullability(ConeNullability.NOT_NULL, context.session.typeContext), - declaration.constructType(emptyArray(), false), - context - ) - } + val missingSuperTypes = context.session.missingDependencyStorage.getMissingSuperTypes(declaration) + for (superType in missingSuperTypes) { + reporter.reportOn( + source, + FirErrors.MISSING_DEPENDENCY_SUPERCLASS, + superType.withArguments(emptyArray()).withNullability(ConeNullability.NOT_NULL, context.session.typeContext), + declaration.constructType(emptyArray(), false), + context + ) } - return missingSupertype - } - - private fun FirClassSymbol<*>.collectSuperTypes(session: FirSession): Set { - val superTypes = mutableSetOf() - fun collect(symbol: FirClassSymbol<*>) { - for (superType in symbol.resolvedSuperTypes) { - if (superTypes.add(superType)) { - (superType.toSymbol(session) as? FirClassSymbol<*>)?.let(::collect) - } - } - } - collect(this) - return superTypes + return missingSuperTypes.isNotEmpty() } } diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt index a8dc304ef54..98ed045e2b8 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt @@ -92,6 +92,7 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion register(FirAnnotationsPlatformSpecificSupportComponent::class, FirAnnotationsPlatformSpecificSupportComponent.Default) register(FirPrimaryConstructorSuperTypeCheckerPlatformComponent::class, FirPrimaryConstructorSuperTypeCheckerPlatformComponent.Default) register(FirGenericArrayClassLiteralSupport::class, FirGenericArrayClassLiteralSupport.Disabled) + register(FirMissingDependencyStorage::class, FirMissingDependencyStorage(this)) } @OptIn(SessionConfiguration::class) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirMissingDependencyStorage.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirMissingDependencyStorage.kt new file mode 100644 index 00000000000..69727f65551 --- /dev/null +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/FirMissingDependencyStorage.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.types + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSessionComponent +import org.jetbrains.kotlin.fir.ThreadSafeMutableState +import org.jetbrains.kotlin.fir.caches.firCachesFactory +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol + +@ThreadSafeMutableState +class FirMissingDependencyStorage(private val session: FirSession) : FirSessionComponent { + private val cache = + session.firCachesFactory.createCache, Set, Nothing?> { symbol, _ -> + findMissingSuperTypes(symbol) + } + + fun getMissingSuperTypes(declaration: FirClassSymbol<*>): Set { + return cache.getValue(declaration, null) + } + + private fun findMissingSuperTypes(declaration: FirClassSymbol<*>): Set { + return declaration.collectSuperTypes(session) + .filterTo(mutableSetOf()) { + // Ignore types which are already errors. + it !is ConeErrorType && it !is ConeDynamicType && it.toSymbol(session) == null + } + } + + private fun FirClassSymbol<*>.collectSuperTypes(session: FirSession): Set { + val superTypes = mutableSetOf() + fun collect(symbol: FirClassSymbol<*>) { + for (superTypeRef in symbol.resolvedSuperTypeRefs) { + val superType = superTypeRef.type + if (!superType.isAny && superTypes.add(superType)) { + (superType.toSymbol(session) as? FirClassSymbol<*>)?.let(::collect) + } + } + } + collect(this) + return superTypes + } +} + +val FirSession.missingDependencyStorage: FirMissingDependencyStorage by FirSession.sessionComponentAccessor() diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.kt index 13291f18219..a80f085d290 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.kt @@ -149,7 +149,7 @@ abstract class AbstractCompileKotlinAgainstCustomBinariesTest : AbstractKotlinCo compileKotlin("source.kt", tmpdir, listOf(compileLibrary("library-1"), compileLibrary("library-2"))) } - // KT-60778 K2: implement MISSING_DEPENDENCY_CLASS(_SUPERCLASS) errors + // KT-62900 K2: Expected expression to be resolved during Fir2Ir fun testMissingEnumReferencedInAnnotationArgument() = muteForK2 { doTestBrokenLibrary("library", "a/E.class") }