[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:
Nikita Bobko
2023-10-25 22:15:51 +02:00
committed by teamcity
parent 664b9cc3ba
commit eb0c8c00c3
16 changed files with 181 additions and 170 deletions
@@ -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
@@ -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 ----------------------------------------
@@ -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,
@@ -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