diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirMultiplatformInfoProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirMultiplatformInfoProvider.kt index 46bbac8e3d0..6af6dfbe4c5 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirMultiplatformInfoProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirMultiplatformInfoProvider.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.expectForActual import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol -import org.jetbrains.kotlin.resolve.multiplatform.isCompatibleOrWeaklyIncompatible +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility internal class KtFirMultiplatformInfoProvider( override val analysisSession: KtFirAnalysisSession, @@ -31,10 +31,7 @@ internal class KtFirMultiplatformInfoProvider( } if (status?.isActual != true) return emptyList() - return firSymbol.expectForActual.orEmpty().asSequence() - .filter { it.key.isCompatibleOrWeaklyIncompatible } - .flatMap { it.value } - .map { analysisSession.firSymbolBuilder.buildSymbol(it) as KtDeclarationSymbol } - .toList() + return firSymbol.expectForActual?.get(ExpectActualMatchingCompatibility.MatchedSuccessfully) + ?.map { analysisSession.firSymbolBuilder.buildSymbol(it) as KtDeclarationSymbol }.orEmpty() } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualCallableDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualCallableDeclarationChecker.kt index dc2747b7b0f..41e785374df 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualCallableDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualCallableDeclarationChecker.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.types.areCompatibleExpectActualTypes import org.jetbrains.kotlin.fir.types.createExpectActualTypeParameterSubstitutor import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility import org.jetbrains.kotlin.utils.zipIfSizesAreEqual object FirActualCallableDeclarationChecker : FirCallableDeclarationChecker() { @@ -60,7 +61,7 @@ object FirActualCallableDeclarationChecker : FirCallableDeclarationChecker() { callableDeclaration.source, FirErrors.ACTUAL_WITHOUT_EXPECT, actualFunctionSymbol, - actualFunctionSymbol.expectForActual as Map>, Collection>>, + actualFunctionSymbol.expectForActual as Map>>, context ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker.kt index e078faa9337..ffcd7307a15 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker -import org.jetbrains.kotlin.resolve.multiplatform.compatible +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility internal object FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker : FirRegularClassChecker() { override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { @@ -77,7 +77,8 @@ internal object FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker : Fir expectSymbol, actualSymbol, actualMember, checkClassScopesCompatibility = false ) - val expectMember: DeclarationSymbolMarker = potentialExpects.entries.singleOrNull { it.value.compatible }?.key + val expectMember: DeclarationSymbolMarker = potentialExpects.entries + .singleOrNull { it.value == ExpectActualMatchingCompatibility.MatchedSuccessfully }?.key ?: potentialExpects.keys.singleOrNull() ?: return null return expectMember as FirNamedFunctionSymbol diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt index 28fe8b1a8b3..db12c422b41 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt @@ -9,8 +9,7 @@ import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.diagnostics.* -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors @@ -19,22 +18,22 @@ import org.jetbrains.kotlin.fir.declarations.utils.isActual import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.isExternal import org.jetbrains.kotlin.fir.declarations.utils.isTailRec -import org.jetbrains.kotlin.fir.expectActualMatchingContextFactory import org.jetbrains.kotlin.fir.expressions.FirAnnotation -import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker +import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualChecker import org.jetbrains.kotlin.resolve.checkers.OptInNames import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCheckingCompatibility import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.MismatchOrIncompatible import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility -import org.jetbrains.kotlin.resolve.multiplatform.isCompatibleOrWeaklyIncompatible @Suppress("DuplicatedCode") object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { @@ -120,20 +119,35 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter, - checkActual: Boolean = true + checkActual: Boolean = true, ) { val symbol = declaration.symbol - val compatibilityToMembersMap = symbol.expectForActual ?: return + val matchingCompatibilityToMembersMap = symbol.expectForActual ?: return + val expectedSingleCandidate = + matchingCompatibilityToMembersMap[ExpectActualMatchingCompatibility.MatchedSuccessfully]?.singleOrNull() + val checkingCompatibility = if (expectedSingleCandidate != null) { + val expectActualMatchingContext = context.session.expectActualMatchingContextFactory.create( + context.session, context.scopeSession, + allowedWritingMemberExpectForActualMapping = true, + ) + val actualContainingClass = context.containingDeclarations.lastOrNull()?.symbol as? FirRegularClassSymbol + val expectContainingClass = actualContainingClass?.getSingleExpectForActualOrNull() as? FirRegularClassSymbol + getCheckingCompatibility( + symbol, + expectedSingleCandidate, + actualContainingClass, + expectContainingClass, + expectActualMatchingContext, + ) + } else null - checkAmbiguousExpects(symbol, compatibilityToMembersMap, symbol, context, reporter) + checkAmbiguousExpects(symbol, matchingCompatibilityToMembersMap, symbol, context, reporter) val source = declaration.source if (!declaration.isActual) { - if (compatibilityToMembersMap.allMismatches()) return + if (matchingCompatibilityToMembersMap.allMismatches()) return - if (ExpectActualCheckingCompatibility.Compatible in compatibilityToMembersMap || - ExpectActualMatchingCompatibility.MatchedSuccessfully in compatibilityToMembersMap - ) { + if (ExpectActualMatchingCompatibility.MatchedSuccessfully in matchingCompatibilityToMembersMap) { if (checkActual) { reporter.reportOn(source, FirErrors.ACTUAL_MISSING, context) } @@ -141,9 +155,8 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { } } - val singleIncompatibility = compatibilityToMembersMap.keys.singleOrNull() when { - singleIncompatibility is ExpectActualCheckingCompatibility.ClassScopes -> { + checkingCompatibility is ExpectActualCheckingCompatibility.ClassScopes -> { require(symbol is FirRegularClassSymbol || symbol is FirTypeAliasSymbol) { "Incompatible.ClassScopes is only possible for a class or a typealias: $declaration" } @@ -153,7 +166,7 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { // This is needed only to reduce the number of errors. Incompatibility errors for those members will be reported // later when this checker is called for them fun hasSingleActualSuspect( - expectedWithIncompatibility: Pair, Map>, Collection>>> + expectedWithIncompatibility: Pair, Map>, Collection>>>, ): Boolean { val (expectedMember, incompatibility) = expectedWithIncompatibility val actualMember = incompatibility.values.singleOrNull()?.singleOrNull() @@ -163,8 +176,8 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { actualMember.fir.expectForActual?.values?.singleOrNull()?.singleOrNull() == expectedMember } - val nonTrivialIncompatibleMembers = singleIncompatibility.incompatibleMembers.filterNot(::hasSingleActualSuspect) - val nonTrivialMismatchedMembers = singleIncompatibility.mismatchedMembers.filterNot(::hasSingleActualSuspect) + val nonTrivialIncompatibleMembers = checkingCompatibility.incompatibleMembers.filterNot(::hasSingleActualSuspect) + val nonTrivialMismatchedMembers = checkingCompatibility.mismatchedMembers.filterNot(::hasSingleActualSuspect) if (nonTrivialIncompatibleMembers.isNotEmpty()) { reporter.reportOn(source, FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, symbol, nonTrivialIncompatibleMembers, context) @@ -173,17 +186,28 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { } } - ExpectActualCheckingCompatibility.Compatible !in compatibilityToMembersMap && - ExpectActualMatchingCompatibility.MatchedSuccessfully !in compatibilityToMembersMap -> { + ExpectActualMatchingCompatibility.MatchedSuccessfully !in matchingCompatibilityToMembersMap && + requireActualModifier(declaration.symbol, context.session) -> { + reporter.reportOn( + source, + FirErrors.ACTUAL_WITHOUT_EXPECT, + symbol, + matchingCompatibilityToMembersMap, + context + ) + } + + checkingCompatibility != null && checkingCompatibility != ExpectActualCheckingCompatibility.Compatible -> { + check(expectedSingleCandidate != null) // It can't be null, because checkingCompatibility is not null // A nicer diagnostic for functions with default params - if (declaration is FirFunction && compatibilityToMembersMap.keys.any { it is ExpectActualCheckingCompatibility.ActualFunctionWithDefaultParameters }) { + if (declaration is FirFunction && checkingCompatibility == ExpectActualCheckingCompatibility.ActualFunctionWithDefaultParameters) { reporter.reportOn(declaration.source, FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS, context) } else if (requireActualModifier(declaration.symbol, context.session)) { reporter.reportOn( source, FirErrors.ACTUAL_WITHOUT_EXPECT, symbol, - compatibilityToMembersMap, + mapOf(checkingCompatibility to listOf(expectedSingleCandidate)), context ) } @@ -191,27 +215,49 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { else -> {} } - // We want to report errors even if a candidate is incompatible, but it's single - val expectedSingleCandidate = symbol.getSingleExpectForActualOrNull() if (expectedSingleCandidate != null) { checkOptInAnnotation(declaration, expectedSingleCandidate, context, reporter) checkAnnotationsMatch(expectedSingleCandidate, symbol, context, reporter) } } + private fun getCheckingCompatibility( + actualSymbol: FirBasedSymbol<*>, + expectSymbol: FirBasedSymbol<*>, + actualContainingClass: FirRegularClassSymbol?, + expectContainingClass: FirRegularClassSymbol?, + context: FirExpectActualMatchingContext, + ): ExpectActualCompatibility> = + when { + actualSymbol is FirCallableSymbol<*> && expectSymbol is FirCallableSymbol<*> -> { + AbstractExpectActualChecker.getCallablesCompatibility( + expectSymbol, + actualSymbol, + expectContainingClass, + actualContainingClass, + context, + ) + } + actualSymbol is FirClassLikeSymbol<*> && expectSymbol is RegularClassSymbolMarker -> { + AbstractExpectActualChecker.getClassifiersCompatibility( + expectSymbol, + actualSymbol, + checkClassScopesCompatibility = true, + context, + ) + } + else -> error("These expect/actual shouldn't have been matched by FirExpectActualResolver") + } + private fun checkAmbiguousExpects( actualDeclaration: FirBasedSymbol<*>, - compatibility: Map>, List>>, + compatibility: Map>>, symbol: FirBasedSymbol<*>, context: CheckerContext, reporter: DiagnosticReporter ) { - val filesWithAtLeastWeaklyCompatibleExpects = compatibility.asSequence() - .filter { (compatibility, _) -> - compatibility.isCompatibleOrWeaklyIncompatible - } - .map { (_, members) -> members } - .flatten() + val filesWithAtLeastWeaklyCompatibleExpects = compatibility[ExpectActualMatchingCompatibility.MatchedSuccessfully] + .orEmpty() .map { it.moduleData } .sortedBy { it.name.asString() } .toList() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt index af9cc0392d4..be6a28f454e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt @@ -451,7 +451,7 @@ class FirExpectActualMatchingContextImpl private constructor( return symbol.source == null && symbol.origin !is FirDeclarationOrigin.Plugin } - override fun onMatchedOrCompatibleMembers( + override fun onMatchedMembers( expectSymbol: DeclarationSymbolMarker, actualSymbol: DeclarationSymbolMarker, containingExpectClassSymbol: RegularClassSymbolMarker?, @@ -469,7 +469,7 @@ class FirExpectActualMatchingContextImpl private constructor( override fun onMismatchedOrIncompatibleMembersFromClassScope( expectSymbol: DeclarationSymbolMarker, - actualSymbolsByIncompatibility: Map, List>, + actualSymbolsByIncompatibility: Map>, containingExpectClassSymbol: RegularClassSymbolMarker?, containingActualClassSymbol: RegularClassSymbolMarker? ) { @@ -489,7 +489,7 @@ class FirExpectActualMatchingContextImpl private constructor( private fun FirRegularClassSymbol.addMemberExpectForActualMapping( expectMember: FirBasedSymbol<*>, actualMember: FirBasedSymbol<*>, - expectClassSymbol: FirRegularClassSymbol, compatibility: ExpectActualCompatibility<*>, + expectClassSymbol: FirRegularClassSymbol, compatibility: ExpectActualMatchingCompatibility, ) { check(allowedWritingMemberExpectForActualMapping) { "Writing memberExpectForActual is not allowed in this context" } val fir = fir @@ -524,7 +524,7 @@ class FirExpectActualMatchingContextImpl private constructor( actualClass: RegularClassSymbolMarker, actualMember: DeclarationSymbolMarker, checkClassScopesCompatibility: Boolean, - ): Map, ExpectActualCompatibility<*>> { + ): Map, ExpectActualMatchingCompatibility> { val mapping = actualClass.asSymbol().fir.memberExpectForActual return mapping?.get(actualMember to expectClass) ?: emptyMap() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualResolver.kt index f3bc34b1678..3634b0b5333 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualResolver.kt @@ -7,19 +7,20 @@ package org.jetbrains.kotlin.fir.resolve.transformers.mpp import org.jetbrains.kotlin.fir.FirExpectActualMatchingContext import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.resolve.* +import org.jetbrains.kotlin.fir.declarations.ExpectForActualMatchingData +import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol -import org.jetbrains.kotlin.fir.symbols.impl.* -import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.mpp.CallableSymbolMarker -import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualChecker -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility +import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualMatcher import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility -import org.jetbrains.kotlin.resolve.multiplatform.getMatchedAndChecked object FirExpectActualResolver { fun findExpectForActual( @@ -27,9 +28,9 @@ object FirExpectActualResolver { useSiteSession: FirSession, scopeSession: ScopeSession, context: FirExpectActualMatchingContext, - ): ExpectForActualData { + ): ExpectForActualMatchingData { with(context) { - val result = when (actualSymbol) { + val result: Map>> = when (actualSymbol) { is FirCallableSymbol<*> -> { val callableId = actualSymbol.callableId val classId = callableId.classId @@ -60,7 +61,7 @@ object FirExpectActualResolver { candidates.filter { expectSymbol -> actualSymbol != expectSymbol && expectSymbol.isExpect }.groupBy { expectDeclaration -> - AbstractExpectActualChecker.getCallablesCompatibility( + AbstractExpectActualMatcher.getCallablesMatchingCompatibility( expectDeclaration, actualSymbol as CallableSymbolMarker, expectContainingClass, @@ -69,21 +70,16 @@ object FirExpectActualResolver { ) }.let { // If there is a compatible entry, return a map only containing it - when (val compatibleSymbols = it.getMatchedAndChecked()) { + when (val compatibleSymbols = it[ExpectActualMatchingCompatibility.MatchedSuccessfully]) { null -> it - else -> mapOf>, _>(ExpectActualMatchingCompatibility.MatchedSuccessfully to compatibleSymbols) + else -> mapOf(ExpectActualMatchingCompatibility.MatchedSuccessfully to compatibleSymbols) } } } is FirClassLikeSymbol<*> -> { val expectClassSymbol = useSiteSession.dependenciesSymbolProvider .getClassLikeSymbolByClassId(actualSymbol.classId) as? FirRegularClassSymbol ?: return emptyMap() - val compatibility = AbstractExpectActualChecker.getClassifiersCompatibility( - expectClassSymbol, - actualSymbol, - checkClassScopesCompatibility = true, - context - ) + val compatibility = AbstractExpectActualMatcher.matchClassifiers(expectClassSymbol, actualSymbol, context) mapOf(compatibility to listOf(expectClassSymbol)) } else -> emptyMap() diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/ExpectActualAttributes.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/ExpectActualAttributes.kt index 774114109ab..b64affc6b40 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/ExpectActualAttributes.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/ExpectActualAttributes.kt @@ -10,12 +10,11 @@ import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility -import org.jetbrains.kotlin.resolve.multiplatform.isCompatibleOrWeaklyIncompatible +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility private object ExpectForActualAttributeKey : FirDeclarationDataKey() -typealias ExpectForActualData = Map>, List>> +typealias ExpectForActualMatchingData = Map>> /** * Actual declaration -> (many) expect declaration mapping. For top-level declarations. @@ -27,7 +26,7 @@ typealias ExpectForActualData = Map> * See `/docs/fir/k2_kmp.md` */ @SymbolInternals -var FirDeclaration.expectForActual: ExpectForActualData? by FirDeclarationDataRegistry.data(ExpectForActualAttributeKey) +var FirDeclaration.expectForActual: ExpectForActualMatchingData? by FirDeclarationDataRegistry.data(ExpectForActualAttributeKey) /** * @see expectForActual @@ -38,17 +37,13 @@ fun FirFunctionSymbol<*>.getSingleExpectForActualOrNull(): FirFunctionSymbol<*>? /** * @see expectForActual */ -fun FirBasedSymbol<*>.getSingleExpectForActualOrNull(): FirBasedSymbol<*>? { - val expectForActual = expectForActual ?: return null - val compatibleOrWeakCompatible: List> = - expectForActual.entries.singleOrNull { it.key.isCompatibleOrWeaklyIncompatible }?.value ?: return null - return compatibleOrWeakCompatible.singleOrNull() -} +fun FirBasedSymbol<*>.getSingleExpectForActualOrNull(): FirBasedSymbol<*>? = + expectForActual?.get(ExpectActualMatchingCompatibility.MatchedSuccessfully)?.singleOrNull() /** * @see expectForActual */ -val FirBasedSymbol<*>.expectForActual: ExpectForActualData? +val FirBasedSymbol<*>.expectForActual: ExpectForActualMatchingData? get() { lazyResolveToPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING) return fir.expectForActual @@ -61,7 +56,7 @@ private object MemberExpectForActualAttributeKey : FirDeclarationDataKey() // in case when two `actual typealias` point to the same class. typealias MemberExpectForActualData = Map, /* expect class */ FirRegularClassSymbol>, - Map, ExpectActualCompatibility<*>>> + Map, ExpectActualMatchingCompatibility>> /** * Actual class + expect class + actual member declaration -> (many) expect member declaration mapping. diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt index bfa1f3bd025..a34b8d65764 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt @@ -10,7 +10,9 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.PsiIrFileEntry import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol import org.jetbrains.kotlin.ir.types.IrTypeSystemContext import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.callableId @@ -20,8 +22,8 @@ import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualChecker -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility +import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualMatcher +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility import java.io.File /** @@ -219,11 +221,10 @@ private class ExpectActualLinkCollector : IrElementVisitor, context: MatchingContext ) { - AbstractExpectActualChecker.checkSingleExpectTopLevelDeclarationAgainstPotentialActuals( + AbstractExpectActualMatcher.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals( expectSymbol, actualSymbols, context, - checkClassScopesCompatibility = true ) } @@ -260,7 +261,7 @@ private class ExpectActualLinkCollector : IrElementVisitor, List>, + actualSymbolsByIncompatibility: Map>, containingExpectClassSymbol: RegularClassSymbolMarker?, containingActualClassSymbol: RegularClassSymbolMarker?, ) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt index 383300e584d..32886c0f689 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.IrTypeSystemContext import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualChecker +import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualMatcher import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil @@ -45,11 +45,10 @@ internal fun collectActualCallablesMatchingToSpecificExpect( matchingActuals += actualSymbol } } - AbstractExpectActualChecker.checkSingleExpectTopLevelDeclarationAgainstPotentialActuals( + AbstractExpectActualMatcher.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals( expectSymbol, actualSymbols, context, - checkClassScopesCompatibility = false ) return matchingActuals } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt index 4850877537c..8d13a82e36a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualCollectionArgumentsCom import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo import org.jetbrains.kotlin.resolve.checkers.OptInNames -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.TypeCheckerState import org.jetbrains.kotlin.types.Variance @@ -480,7 +480,7 @@ internal abstract class IrExpectActualMatchingContext( } } - override fun onMatchedOrCompatibleMembers( + override fun onMatchedMembers( expectSymbol: DeclarationSymbolMarker, actualSymbol: DeclarationSymbolMarker, containingExpectClassSymbol: RegularClassSymbolMarker?, @@ -558,7 +558,7 @@ internal abstract class IrExpectActualMatchingContext( actualClass: RegularClassSymbolMarker, actualMember: DeclarationSymbolMarker, checkClassScopesCompatibility: Boolean, - ): Map> = error("Should not be called") + ): Map = error("Should not be called") // It's a stub, because not needed anywhere private object IrSourceElementStub : SourceElementMarker diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt index 4b610da9259..9843fced9a9 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.resolve.checkers.OptInNames import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.utils.zipIfSizesAreEqual +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType as IncompatibilityType object AbstractExpectActualAnnotationMatchChecker { @@ -316,7 +317,7 @@ object AbstractExpectActualAnnotationMatchChecker { checkClassScopesCompatibility = false, ) val expectMember = expectToCompatibilityMap - .filter { it.value is ExpectActualCompatibility.MatchedOrCompatible }.keys.singleOrNull() + .filter { it.value == ExpectActualMatchingCompatibility.MatchedSuccessfully }.keys.singleOrNull() // Check also incompatible members if only one is found ?: expectToCompatibilityMap.keys.singleOrNull() ?: continue diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt index f6e56a9085b..6452ede366f 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt @@ -13,8 +13,6 @@ import org.jetbrains.kotlin.mpp.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCheckingCompatibility -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.MismatchOrIncompatible import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker @@ -37,12 +35,17 @@ object AbstractExpectActualChecker { actualClassLikeSymbol: ClassLikeSymbolMarker, checkClassScopesCompatibility: Boolean, context: ExpectActualMatchingContext, - ): ExpectActualCompatibility { + ): ExpectActualCheckingCompatibility { val result = with(context) { - getClassifiersCompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor = null, checkClassScopesCompatibility) + getClassifiersCompatibility( + expectClassSymbol, + actualClassLikeSymbol, + parentSubstitutor = null, + checkClassScopesCompatibility, + ) } @Suppress("UNCHECKED_CAST") - return result as ExpectActualCompatibility + return result as ExpectActualCheckingCompatibility } fun getCallablesCompatibility( @@ -51,7 +54,7 @@ object AbstractExpectActualChecker { expectContainingClass: RegularClassSymbolMarker?, actualContainingClass: RegularClassSymbolMarker?, context: ExpectActualMatchingContext, - ): ExpectActualCompatibility = with (context) { + ): ExpectActualCheckingCompatibility = with (context) { val expectTypeParameters = expectContainingClass?.typeParameters.orEmpty() val actualTypeParameters = actualContainingClass?.typeParameters.orEmpty() val parentSubstitutor = (expectTypeParameters zipIfSizesAreEqual actualTypeParameters) @@ -61,10 +64,10 @@ object AbstractExpectActualChecker { actualDeclaration, parentSubstitutor, expectContainingClass, - actualContainingClass + actualContainingClass, ) @Suppress("UNCHECKED_CAST") - result as ExpectActualCompatibility + result as ExpectActualCheckingCompatibility } fun checkSingleExpectTopLevelDeclarationAgainstPotentialActuals( @@ -93,7 +96,12 @@ object AbstractExpectActualChecker { actualClassLikeSymbol: ClassLikeSymbolMarker, parentSubstitutor: TypeSubstitutorMarker?, checkClassScopes: Boolean, - ): ExpectActualCheckingCompatibility<*> = getClassifiersIncompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor, checkClassScopes) + ): ExpectActualCheckingCompatibility<*> = getClassifiersIncompatibility( + expectClassSymbol, + actualClassLikeSymbol, + parentSubstitutor, + checkClassScopes, + ) ?: ExpectActualCheckingCompatibility.Compatible context(ExpectActualMatchingContext<*>) @@ -301,27 +309,17 @@ object AbstractExpectActualChecker { } } - val mismatchedOrIncompatibleMap = mutableMapOf, MutableList>() + val incompatibilityMap = mutableMapOf, MutableList>() for ((actualMember, compatibility) in mapping) { when (compatibility) { - is ExpectActualCompatibility.MatchedOrCompatible<*> -> { - onMatchedOrCompatibleMembers(expectMember, actualMember, expectClassSymbol, actualClassSymbol) - return - } - - is MismatchOrIncompatible<*> -> mismatchedOrIncompatibleMap.getOrPut(compatibility) { SmartList() }.add(actualMember) + ExpectActualCheckingCompatibility.Compatible -> return + is ExpectActualCheckingCompatibility.Incompatible<*> -> incompatibilityMap.getOrPut(compatibility) { SmartList() }.add(actualMember) } } - // todo it's temporary code. KT-62590 in progress - val incompatibilities = mismatchedOrIncompatibleMap - .mapNotNull { (key, value) -> - (key as? ExpectActualCheckingCompatibility.Incompatible)?.let { it to value } - } - .toMap() - - incompatibleMembers?.add(expectMember to incompatibilities) - onMismatchedOrIncompatibleMembersFromClassScope(expectMember, mismatchedOrIncompatibleMap, expectClassSymbol, actualClassSymbol) + incompatibleMembers?.add(expectMember to incompatibilityMap) + // Temporarily comment out reporting checking incompatibilities to backend. KT-62590 is in progress + //onMismatchedOrIncompatibleMembersFromClassScope(expectMember, incompatibilityMap, expectClassSymbol, actualClassSymbol) } context(ExpectActualMatchingContext<*>) @@ -331,7 +329,7 @@ object AbstractExpectActualChecker { parentSubstitutor: TypeSubstitutorMarker?, expectContainingClass: RegularClassSymbolMarker?, actualContainingClass: RegularClassSymbolMarker?, - ): ExpectActualCompatibility<*> { + ): ExpectActualCheckingCompatibility<*> { require( (expectDeclaration is ConstructorSymbolMarker && actualDeclaration is ConstructorSymbolMarker) || expectDeclaration.callableId.callableName == actualDeclaration.callableId.callableName @@ -352,18 +350,15 @@ object AbstractExpectActualChecker { return ExpectActualCheckingCompatibility.Compatible } - // We must prioritize to return STRONG incompatible over WEAK incompatible (because STRONG incompatibility allows to search for overloads) val annotationMode = expectContainingClass?.classKind == ClassKind.ANNOTATION_CLASS - return getCallablesStrongIncompatibility(expectDeclaration, actualDeclaration, annotationMode, parentSubstitutor) - ?: getCallablesWeakIncompatibility( - expectDeclaration, - actualDeclaration, - annotationMode, - parentSubstitutor, - expectContainingClass, - actualContainingClass - ) - ?: ExpectActualCheckingCompatibility.Compatible + return getCallablesCheckingIncompatibility( + expectDeclaration, + actualDeclaration, + annotationMode, + parentSubstitutor, + expectContainingClass, + actualContainingClass, + ) ?: ExpectActualCheckingCompatibility.Compatible } context(ExpectActualMatchingContext<*>) @@ -423,14 +418,14 @@ object AbstractExpectActualChecker { } context(ExpectActualMatchingContext<*>) - private fun getCallablesWeakIncompatibility( + private fun getCallablesCheckingIncompatibility( expectDeclaration: CallableSymbolMarker, actualDeclaration: CallableSymbolMarker, insideAnnotationClass: Boolean, parentSubstitutor: TypeSubstitutorMarker?, expectContainingClass: RegularClassSymbolMarker?, actualContainingClass: RegularClassSymbolMarker?, - ): ExpectActualCheckingCompatibility<*>? { + ): ExpectActualCheckingCompatibility.Incompatible<*>? { val expectedTypeParameters = expectDeclaration.typeParameters val actualTypeParameters = actualDeclaration.typeParameters val expectedValueParameters = expectDeclaration.valueParameters @@ -679,7 +674,7 @@ object AbstractExpectActualChecker { private fun getFunctionsIncompatibility( expectFunction: CallableSymbolMarker, actualFunction: CallableSymbolMarker, - ): ExpectActualCheckingCompatibility<*>? { + ): ExpectActualCheckingCompatibility.Incompatible<*>? { if (!equalBy(expectFunction, actualFunction) { f -> f.isSuspend }) { return ExpectActualCheckingCompatibility.FunctionModifiersDifferent } @@ -699,12 +694,13 @@ object AbstractExpectActualChecker { private fun getPropertiesIncompatibility( expected: PropertySymbolMarker, actual: PropertySymbolMarker, - ): ExpectActualCheckingCompatibility<*>? { + ): ExpectActualCheckingCompatibility.Incompatible<*>? { return when { !equalBy(expected, actual) { p -> p.isVar } -> ExpectActualCheckingCompatibility.PropertyKind !equalBy(expected, actual) { p -> p.isLateinit } -> ExpectActualCheckingCompatibility.PropertyLateinitModifier expected.isConst && !actual.isConst -> ExpectActualCheckingCompatibility.PropertyConstModifier - !arePropertySettersWithCompatibleVisibilities(expected, actual) -> ExpectActualCheckingCompatibility.PropertySetterVisibility + !arePropertySettersWithCompatibleVisibilities(expected, actual) -> + ExpectActualCheckingCompatibility.PropertySetterVisibility else -> null } } @@ -716,7 +712,11 @@ object AbstractExpectActualChecker { ): Boolean { val expectedSetter = expected.setter ?: return true val actualSetter = actual.setter ?: return true - return areCompatibleCallableVisibilities(expectedSetter.visibility, expectedSetter.modality, actualSetter.visibility) + return areCompatibleCallableVisibilities( + expectedSetter.visibility, + expectedSetter.modality, + actualSetter.visibility, + ) } // ---------------------------------------- Utils ---------------------------------------- diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualMatcher.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualMatcher.kt index 635bce9d320..ffe27f1414b 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualMatcher.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualMatcher.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.mpp.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker @@ -27,26 +26,24 @@ import org.jetbrains.kotlin.utils.zipIfSizesAreEqual * See `/docs/fir/k2_kmp.md` for details */ object AbstractExpectActualMatcher { - fun getCallablesCompatibility( + fun getCallablesMatchingCompatibility( expectDeclaration: CallableSymbolMarker, actualDeclaration: CallableSymbolMarker, expectContainingClass: RegularClassSymbolMarker?, actualContainingClass: RegularClassSymbolMarker?, - context: ExpectActualMatchingContext, - ): ExpectActualCompatibility = with (context) { + context: ExpectActualMatchingContext<*>, + ): ExpectActualMatchingCompatibility = with (context) { val expectTypeParameters = expectContainingClass?.typeParameters.orEmpty() val actualTypeParameters = actualContainingClass?.typeParameters.orEmpty() val parentSubstitutor = (expectTypeParameters zipIfSizesAreEqual actualTypeParameters) ?.let { createExpectActualTypeParameterSubstitutor(it, parentSubstitutor = null) } - val result = getCallablesCompatibility( + getCallablesCompatibility( expectDeclaration, actualDeclaration, parentSubstitutor, expectContainingClass, actualContainingClass ) - @Suppress("UNCHECKED_CAST") - result as ExpectActualCompatibility } fun matchSingleExpectTopLevelDeclarationAgainstPotentialActuals( @@ -147,7 +144,7 @@ object AbstractExpectActualMatcher { for ((actualMember, compatibility) in mapping) { when (compatibility) { ExpectActualMatchingCompatibility.MatchedSuccessfully -> { - onMatchedOrCompatibleMembers(expectMember, actualMember, expectClassSymbol, actualClassSymbol) + onMatchedMembers(expectMember, actualMember, expectClassSymbol, actualClassSymbol) return actualMember } @@ -189,12 +186,12 @@ object AbstractExpectActualMatcher { } val annotationMode = expectContainingClass?.classKind == ClassKind.ANNOTATION_CLASS - return getCallablesStrongIncompatibility(expectDeclaration, actualDeclaration, annotationMode, parentSubstitutor) + return getCallablesMatchingIncompatibility(expectDeclaration, actualDeclaration, annotationMode, parentSubstitutor) ?: ExpectActualMatchingCompatibility.MatchedSuccessfully } context(ExpectActualMatchingContext<*>) - private fun getCallablesStrongIncompatibility( + private fun getCallablesMatchingIncompatibility( expectDeclaration: CallableSymbolMarker, actualDeclaration: CallableSymbolMarker, insideAnnotationClass: Boolean, diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt index 4f6412143f4..3107e3a5c5e 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.mpp.* import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker @@ -165,7 +165,7 @@ interface ExpectActualMatchingContext : TypeSystemC val CallableSymbolMarker.hasStableParameterNames: Boolean - fun onMatchedOrCompatibleMembers( + fun onMatchedMembers( expectSymbol: DeclarationSymbolMarker, actualSymbol: DeclarationSymbolMarker, containingExpectClassSymbol: RegularClassSymbolMarker?, @@ -174,7 +174,7 @@ interface ExpectActualMatchingContext : TypeSystemC fun onMismatchedOrIncompatibleMembersFromClassScope( expectSymbol: DeclarationSymbolMarker, - actualSymbolsByIncompatibility: Map, List>, + actualSymbolsByIncompatibility: Map>, containingExpectClassSymbol: RegularClassSymbolMarker?, containingActualClassSymbol: RegularClassSymbolMarker?, ) {} @@ -217,7 +217,7 @@ interface ExpectActualMatchingContext : TypeSystemC actualClass: RegularClassSymbolMarker, actualMember: DeclarationSymbolMarker, checkClassScopesCompatibility: Boolean, - ): Map> + ): Map fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt index a81a54303ed..b5a79890ba9 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt @@ -20,9 +20,6 @@ sealed interface ExpectActualCompatibility { sealed interface MismatchOrIncompatible : ExpectActualCompatibility { val reason: String? } - - // It's temporary class. KT-62590 is in progress - sealed interface MatchedOrCompatible : ExpectActualCompatibility } /** @@ -41,7 +38,7 @@ sealed class ExpectActualMatchingCompatibility : ExpectActualCompatibility + object MatchedSuccessfully : ExpectActualMatchingCompatibility() } /** @@ -96,16 +93,5 @@ sealed class ExpectActualCheckingCompatibility : ExpectActualCompatibilit object ClassTypeParameterUpperBounds : Incompatible(ExpectActualMatchingCompatibility.FunctionTypeParameterUpperBounds.reason) object TypeParameterVariance : Incompatible("declaration-site variances of type parameters are different") object TypeParameterReified : Incompatible("some type parameter is reified in one declaration and non-reified in the other") - object Compatible : ExpectActualCheckingCompatibility(), ExpectActualCompatibility.MatchedOrCompatible + object Compatible : ExpectActualCheckingCompatibility() } - -val ExpectActualCompatibility<*>.isCompatibleOrWeaklyIncompatible: Boolean - get() = this is ExpectActualCompatibility.MatchedOrCompatible || this is ExpectActualCheckingCompatibility - -val ExpectActualCompatibility<*>.compatible: Boolean - get() = this is ExpectActualCompatibility.MatchedOrCompatible - -// It's temporary function. KT-62590 is in progress -fun Map, List>.getMatchedAndChecked(): List? = - (get(ExpectActualMatchingCompatibility.MatchedSuccessfully).orEmpty() + get(ExpectActualCheckingCompatibility.Compatible).orEmpty()) - .takeIf { it.isNotEmpty() } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualMemberDiff.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualMemberDiff.kt index 90a44aa99a0..d5fcdd7b0b3 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualMemberDiff.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualMemberDiff.kt @@ -56,16 +56,7 @@ data class ExpectActualMemberDiff(val kind: Kind, val actualMember } } -fun ExpectActualCompatibility.MismatchOrIncompatible<*>.toMemberDiffKind(): ExpectActualMemberDiff.Kind? = when (this) { - ExpectActualMatchingCompatibility.CallableKind, - ExpectActualMatchingCompatibility.ParameterCount, - ExpectActualMatchingCompatibility.ParameterShape, - ExpectActualMatchingCompatibility.ParameterTypes, - ExpectActualMatchingCompatibility.FunctionTypeParameterCount, - ExpectActualMatchingCompatibility.FunctionTypeParameterUpperBounds, - // It's an awful API. It will be fixed in KT-62752 - -> error("It's not allowed to call this function with receiver: $this") - +fun ExpectActualCheckingCompatibility.Incompatible<*>.toMemberDiffKind(): ExpectActualMemberDiff.Kind? = when (this) { ExpectActualCheckingCompatibility.ReturnType -> ExpectActualMemberDiff.Kind.ReturnTypeChangedInOverride ExpectActualCheckingCompatibility.ClassTypeParameterCount -> error("Not applicable because ExpectActualMemberDiff is about members") ExpectActualCheckingCompatibility.ClassTypeParameterUpperBounds -> error("Not applicable because ExpectActualMemberDiff is about members")