[FIR, IR] 1/2 Minimize usages of ExpectActualCompatibility, MismatchOrIncompatible and MatchedOrCompatible
- Migrate ExpectActualCompatibility -> ExpectActualCheckingCompatibility where the "checker" is expect - Migrate ExpectActualCompatibility -> ExpectActualMatchingCompatibility where the "matching" is expect KT-62590 in progress. A lot of tests start to fail now. I will fix them in next commits Review: https://jetbrains.team/p/kt/reviews/12750/timeline
This commit is contained in:
+3
-6
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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<ExpectActualCompatibility<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>,
|
||||
actualFunctionSymbol.expectForActual as Map<ExpectActualMatchingCompatibility, Collection<FirBasedSymbol<*>>>,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
+3
-2
@@ -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
|
||||
|
||||
+77
-31
@@ -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<FirBasedSymbol<*>, Map<out MismatchOrIncompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>
|
||||
expectedWithIncompatibility: Pair<FirBasedSymbol<*>, Map<out ExpectActualCompatibility.MismatchOrIncompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>,
|
||||
): 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<FirBasedSymbol<*>> =
|
||||
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<ExpectActualCompatibility<FirBasedSymbol<*>>, List<FirBasedSymbol<*>>>,
|
||||
compatibility: Map<ExpectActualMatchingCompatibility, List<FirBasedSymbol<*>>>,
|
||||
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()
|
||||
|
||||
+4
-4
@@ -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<out ExpectActualCompatibility.MismatchOrIncompatible<*>, List<DeclarationSymbolMarker>>,
|
||||
actualSymbolsByIncompatibility: Map<ExpectActualMatchingCompatibility.Mismatch, List<DeclarationSymbolMarker>>,
|
||||
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<FirBasedSymbol<*>, ExpectActualCompatibility<*>> {
|
||||
): Map<FirBasedSymbol<*>, ExpectActualMatchingCompatibility> {
|
||||
val mapping = actualClass.asSymbol().fir.memberExpectForActual
|
||||
return mapping?.get(actualMember to expectClass) ?: emptyMap()
|
||||
}
|
||||
|
||||
+14
-18
@@ -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<ExpectActualMatchingCompatibility, List<FirBasedSymbol<*>>> = 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<ExpectActualCompatibility<FirBasedSymbol<*>>, _>(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()
|
||||
|
||||
+7
-12
@@ -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<ExpectActualCompatibility<FirBasedSymbol<*>>, List<FirBasedSymbol<*>>>
|
||||
typealias ExpectForActualMatchingData = Map<ExpectActualMatchingCompatibility, List<FirBasedSymbol<*>>>
|
||||
|
||||
/**
|
||||
* Actual declaration -> (many) expect declaration mapping. For top-level declarations.
|
||||
@@ -27,7 +26,7 @@ typealias ExpectForActualData = Map<ExpectActualCompatibility<FirBasedSymbol<*>>
|
||||
* 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<FirBasedSymbol<*>> =
|
||||
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<Pair</* actual member */ FirBasedSymbol<*>, /* expect class */ FirRegularClassSymbol>,
|
||||
Map</* expect member */ FirBasedSymbol<*>, ExpectActualCompatibility<*>>>
|
||||
Map</* expect member */ FirBasedSymbol<*>, ExpectActualMatchingCompatibility>>
|
||||
|
||||
/**
|
||||
* Actual class + expect class + actual member declaration -> (many) expect member declaration mapping.
|
||||
|
||||
+7
-6
@@ -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<Unit, ExpectActualLin
|
||||
actualSymbols: List<IrSymbol>,
|
||||
context: MatchingContext
|
||||
) {
|
||||
AbstractExpectActualChecker.checkSingleExpectTopLevelDeclarationAgainstPotentialActuals(
|
||||
AbstractExpectActualMatcher.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals(
|
||||
expectSymbol,
|
||||
actualSymbols,
|
||||
context,
|
||||
checkClassScopesCompatibility = true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -260,7 +261,7 @@ private class ExpectActualLinkCollector : IrElementVisitor<Unit, ExpectActualLin
|
||||
|
||||
override fun onMismatchedOrIncompatibleMembersFromClassScope(
|
||||
expectSymbol: DeclarationSymbolMarker,
|
||||
actualSymbolsByIncompatibility: Map<out ExpectActualCompatibility.MismatchOrIncompatible<*>, List<DeclarationSymbolMarker>>,
|
||||
actualSymbolsByIncompatibility: Map<ExpectActualMatchingCompatibility.Mismatch, List<DeclarationSymbolMarker>>,
|
||||
containingExpectClassSymbol: RegularClassSymbolMarker?,
|
||||
containingActualClassSymbol: RegularClassSymbolMarker?,
|
||||
) {
|
||||
|
||||
+2
-3
@@ -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
|
||||
}
|
||||
|
||||
+3
-3
@@ -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<out DeclarationSymbolMarker, ExpectActualCompatibility<*>> = error("Should not be called")
|
||||
): Map<out DeclarationSymbolMarker, ExpectActualMatchingCompatibility> = error("Should not be called")
|
||||
|
||||
// It's a stub, because not needed anywhere
|
||||
private object IrSourceElementStub : SourceElementMarker
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
+43
-43
@@ -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<T>,
|
||||
): ExpectActualCompatibility<T> {
|
||||
): ExpectActualCheckingCompatibility<T> {
|
||||
val result = with(context) {
|
||||
getClassifiersCompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor = null, checkClassScopesCompatibility)
|
||||
getClassifiersCompatibility(
|
||||
expectClassSymbol,
|
||||
actualClassLikeSymbol,
|
||||
parentSubstitutor = null,
|
||||
checkClassScopesCompatibility,
|
||||
)
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as ExpectActualCompatibility<T>
|
||||
return result as ExpectActualCheckingCompatibility<T>
|
||||
}
|
||||
|
||||
fun <T : DeclarationSymbolMarker> getCallablesCompatibility(
|
||||
@@ -51,7 +54,7 @@ object AbstractExpectActualChecker {
|
||||
expectContainingClass: RegularClassSymbolMarker?,
|
||||
actualContainingClass: RegularClassSymbolMarker?,
|
||||
context: ExpectActualMatchingContext<T>,
|
||||
): ExpectActualCompatibility<T> = with (context) {
|
||||
): ExpectActualCheckingCompatibility<T> = 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<T>
|
||||
result as ExpectActualCheckingCompatibility<T>
|
||||
}
|
||||
|
||||
fun <T : DeclarationSymbolMarker> 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<MismatchOrIncompatible<*>, MutableList<DeclarationSymbolMarker>>()
|
||||
val incompatibilityMap = mutableMapOf<ExpectActualCheckingCompatibility.Incompatible<*>, MutableList<DeclarationSymbolMarker>>()
|
||||
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 ----------------------------------------
|
||||
|
||||
+7
-10
@@ -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 <T : DeclarationSymbolMarker> getCallablesCompatibility(
|
||||
fun getCallablesMatchingCompatibility(
|
||||
expectDeclaration: CallableSymbolMarker,
|
||||
actualDeclaration: CallableSymbolMarker,
|
||||
expectContainingClass: RegularClassSymbolMarker?,
|
||||
actualContainingClass: RegularClassSymbolMarker?,
|
||||
context: ExpectActualMatchingContext<T>,
|
||||
): ExpectActualCompatibility<T> = 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<T>
|
||||
}
|
||||
|
||||
fun <T : DeclarationSymbolMarker> 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,
|
||||
|
||||
+4
-4
@@ -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<T : DeclarationSymbolMarker> : TypeSystemC
|
||||
|
||||
val CallableSymbolMarker.hasStableParameterNames: Boolean
|
||||
|
||||
fun onMatchedOrCompatibleMembers(
|
||||
fun onMatchedMembers(
|
||||
expectSymbol: DeclarationSymbolMarker,
|
||||
actualSymbol: DeclarationSymbolMarker,
|
||||
containingExpectClassSymbol: RegularClassSymbolMarker?,
|
||||
@@ -174,7 +174,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
||||
|
||||
fun onMismatchedOrIncompatibleMembersFromClassScope(
|
||||
expectSymbol: DeclarationSymbolMarker,
|
||||
actualSymbolsByIncompatibility: Map<out ExpectActualCompatibility.MismatchOrIncompatible<*>, List<DeclarationSymbolMarker>>,
|
||||
actualSymbolsByIncompatibility: Map<ExpectActualMatchingCompatibility.Mismatch, List<DeclarationSymbolMarker>>,
|
||||
containingExpectClassSymbol: RegularClassSymbolMarker?,
|
||||
containingActualClassSymbol: RegularClassSymbolMarker?,
|
||||
) {}
|
||||
@@ -217,7 +217,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
||||
actualClass: RegularClassSymbolMarker,
|
||||
actualMember: DeclarationSymbolMarker,
|
||||
checkClassScopesCompatibility: Boolean,
|
||||
): Map<out DeclarationSymbolMarker, ExpectActualCompatibility<*>>
|
||||
): Map<out DeclarationSymbolMarker, ExpectActualMatchingCompatibility>
|
||||
|
||||
fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker
|
||||
|
||||
|
||||
+2
-16
@@ -20,9 +20,6 @@ sealed interface ExpectActualCompatibility<out D> {
|
||||
sealed interface MismatchOrIncompatible<out D> : ExpectActualCompatibility<D> {
|
||||
val reason: String?
|
||||
}
|
||||
|
||||
// It's temporary class. KT-62590 is in progress
|
||||
sealed interface MatchedOrCompatible<out D> : ExpectActualCompatibility<D>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,7 +38,7 @@ sealed class ExpectActualMatchingCompatibility : ExpectActualCompatibility<Nothi
|
||||
object FunctionTypeParameterCount : Mismatch(TYPE_PARAMETER_COUNT)
|
||||
object ParameterTypes : Mismatch("parameter types are different")
|
||||
object FunctionTypeParameterUpperBounds : Mismatch("upper bounds of type parameters are different")
|
||||
object MatchedSuccessfully : ExpectActualMatchingCompatibility(), ExpectActualCompatibility.MatchedOrCompatible<Nothing>
|
||||
object MatchedSuccessfully : ExpectActualMatchingCompatibility()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,16 +93,5 @@ sealed class ExpectActualCheckingCompatibility<out D> : ExpectActualCompatibilit
|
||||
object ClassTypeParameterUpperBounds : Incompatible<Nothing>(ExpectActualMatchingCompatibility.FunctionTypeParameterUpperBounds.reason)
|
||||
object TypeParameterVariance : Incompatible<Nothing>("declaration-site variances of type parameters are different")
|
||||
object TypeParameterReified : Incompatible<Nothing>("some type parameter is reified in one declaration and non-reified in the other")
|
||||
object Compatible : ExpectActualCheckingCompatibility<Nothing>(), ExpectActualCompatibility.MatchedOrCompatible<Nothing>
|
||||
object Compatible : ExpectActualCheckingCompatibility<Nothing>()
|
||||
}
|
||||
|
||||
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 <T, R> Map<ExpectActualCompatibility<R>, List<T>>.getMatchedAndChecked(): List<T>? =
|
||||
(get(ExpectActualMatchingCompatibility.MatchedSuccessfully).orEmpty() + get(ExpectActualCheckingCompatibility.Compatible).orEmpty())
|
||||
.takeIf { it.isNotEmpty() }
|
||||
|
||||
+1
-10
@@ -56,16 +56,7 @@ data class ExpectActualMemberDiff<out M, out C>(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")
|
||||
|
||||
Reference in New Issue
Block a user