WIP! Tue  3 Oct 17:51:28 CEST 2023
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 069ed79..e612899 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
@@ -5,6 +5,7 @@
 
 package org.jetbrains.kotlin.resolve.calls.mpp
 
+import org.jetbrains.kotlin.config.LanguageVersionSettings
 import org.jetbrains.kotlin.descriptors.ClassKind
 import org.jetbrains.kotlin.descriptors.Modality
 import org.jetbrains.kotlin.descriptors.Visibilities
@@ -29,9 +30,16 @@
         actualClassLikeSymbol: ClassLikeSymbolMarker,
         checkClassScopesCompatibility: Boolean,
         context: ExpectActualMatchingContext<T>,
+        languageVersionSettings: LanguageVersionSettings,
     ): ExpectActualCompatibility<T> {
         val result = with(context) {
-            getClassifiersCompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor = null, checkClassScopesCompatibility)
+            getClassifiersCompatibility(
+                expectClassSymbol,
+                actualClassLikeSymbol,
+                parentSubstitutor = null,
+                checkClassScopesCompatibility,
+                languageVersionSettings,
+            )
         }
         @Suppress("UNCHECKED_CAST")
         return result as ExpectActualCompatibility<T>
@@ -44,9 +52,17 @@
         expectContainingClass: RegularClassSymbolMarker?,
         actualContainingClass: RegularClassSymbolMarker?,
         context: ExpectActualMatchingContext<T>,
+        languageVersionSettings: LanguageVersionSettings
     ): ExpectActualCompatibility<T> {
         val result = with(context) {
-            getCallablesCompatibility(expectDeclaration, actualDeclaration, parentSubstitutor, expectContainingClass, actualContainingClass)
+            getCallablesCompatibility(
+                expectDeclaration,
+                actualDeclaration,
+                parentSubstitutor,
+                expectContainingClass,
+                actualContainingClass,
+                languageVersionSettings,
+            )
         }
         @Suppress("UNCHECKED_CAST")
         return result as ExpectActualCompatibility<T>
@@ -56,6 +72,7 @@
         expectDeclaration: DeclarationSymbolMarker,
         actualDeclarations: List<DeclarationSymbolMarker>,
         context: ExpectActualMatchingContext<T>,
+        languageVersionSettings: LanguageVersionSettings,
     ) {
         with(context) {
             matchSingleExpectAgainstPotentialActuals(
@@ -66,6 +83,7 @@
                 actualClassSymbol = null,
                 unfulfilled = null,
                 checkClassScopesCompatibility = true,
+                languageVersionSettings,
             )
         }
     }
@@ -77,7 +95,14 @@
         actualClassLikeSymbol: ClassLikeSymbolMarker,
         parentSubstitutor: TypeSubstitutorMarker?,
         checkClassScopes: Boolean,
-    ): ExpectActualCompatibility<*> = getClassifiersIncompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor, checkClassScopes)
+        languageVersionSettings: LanguageVersionSettings,
+    ): ExpectActualCompatibility<*> = getClassifiersIncompatibility(
+        expectClassSymbol,
+        actualClassLikeSymbol,
+        parentSubstitutor,
+        checkClassScopes,
+        languageVersionSettings,
+    )
         ?: ExpectActualCompatibility.Compatible
 
     context(ExpectActualMatchingContext<*>)
@@ -87,6 +112,7 @@
         actualClassLikeSymbol: ClassLikeSymbolMarker,
         parentSubstitutor: TypeSubstitutorMarker?,
         checkClassScopesCompatibility: Boolean,
+        languageVersionSettings: LanguageVersionSettings,
     ): ExpectActualCompatibility.Incompatible.ExpectActualCheckingIncompatible<*>? {
         // Can't check FQ names here because nested expected class may be implemented via actual typealias's expansion with the other FQ name
         require(expectClassSymbol.name == actualClassLikeSymbol.name) {
@@ -142,7 +168,7 @@
         }
 
         if (checkClassScopesCompatibility) {
-            getClassScopesIncompatibility(expectClassSymbol, actualClass, substitutor)?.let { return it }
+            getClassScopesIncompatibility(expectClassSymbol, actualClass, substitutor, languageVersionSettings)?.let { return it }
         }
 
         return null
@@ -199,6 +225,7 @@
         expectClassSymbol: RegularClassSymbolMarker,
         actualClassSymbol: RegularClassSymbolMarker,
         substitutor: TypeSubstitutorMarker,
+        languageVersionSettings: LanguageVersionSettings,
     ): Incompatible.ExpectActualCheckingIncompatible<*>? {
         val unfulfilled = arrayListOf<Pair<DeclarationSymbolMarker, Map<Incompatible<*>, List<DeclarationSymbolMarker?>>>>()
 
@@ -220,6 +247,7 @@
                 actualClassSymbol,
                 unfulfilled,
                 checkClassScopesCompatibility = true,
+                languageVersionSettings,
             )
         }
 
@@ -246,6 +274,7 @@
         actualClassSymbol: RegularClassSymbolMarker?,
         unfulfilled: MutableList<Pair<DeclarationSymbolMarker, Map<Incompatible<*>, List<DeclarationSymbolMarker?>>>>?,
         checkClassScopesCompatibility: Boolean,
+        languageVersionSettings: LanguageVersionSettings,
     ) {
         val mapping = actualMembers.keysToMap { actualMember ->
             when (expectMember) {
@@ -254,7 +283,8 @@
                     actualMember as CallableSymbolMarker,
                     substitutor,
                     expectClassSymbol,
-                    actualClassSymbol
+                    actualClassSymbol,
+                    languageVersionSettings
                 )
 
                 is RegularClassSymbolMarker -> {
@@ -264,6 +294,7 @@
                         actualMember as ClassLikeSymbolMarker,
                         parentSubstitutor,
                         checkClassScopesCompatibility,
+                        languageVersionSettings,
                     )
                 }
                 else -> error("Unsupported declaration: $expectMember ($actualMembers)")
@@ -293,6 +324,7 @@
         parentSubstitutor: TypeSubstitutorMarker?,
         expectContainingClass: RegularClassSymbolMarker?,
         actualContainingClass: RegularClassSymbolMarker?,
+        languageVersionSettings: LanguageVersionSettings,
     ): ExpectActualCompatibility<*> {
         require(
             (expectDeclaration is ConstructorSymbolMarker && actualDeclaration is ConstructorSymbolMarker) ||
@@ -321,7 +353,8 @@
                 actualDeclaration,
                 parentSubstitutor,
                 expectContainingClass,
-                actualContainingClass
+                actualContainingClass,
+                languageVersionSettings,
             )
             ?: ExpectActualCompatibility.Compatible
     }
@@ -387,6 +420,7 @@
         parentSubstitutor: TypeSubstitutorMarker?,
         expectContainingClass: RegularClassSymbolMarker?,
         actualContainingClass: RegularClassSymbolMarker?,
+        languageVersionSettings: LanguageVersionSettings,
     ): Incompatible.ExpectActualCheckingIncompatible<*>? {
         val expectedTypeParameters = expectDeclaration.typeParameters
         val actualTypeParameters = actualDeclaration.typeParameters
@@ -426,7 +460,7 @@
             return Incompatible.Modality
         }
 
-        if (!areCompatibleCallableVisibilities(expectDeclaration.visibility, expectModality, actualDeclaration.visibility)) {
+        if (!areCompatibleCallableVisibilities(expectDeclaration.visibility, expectModality, actualDeclaration.visibility, languageVersionSettings)) {
             return Incompatible.Visibility
         }
 
@@ -467,7 +501,7 @@
                 getFunctionsIncompatibility(expectDeclaration, actualDeclaration)?.let { return it }
 
             expectDeclaration is PropertySymbolMarker && actualDeclaration is PropertySymbolMarker ->
-                getPropertiesIncompatibility(expectDeclaration, actualDeclaration)?.let { return it }
+                getPropertiesIncompatibility(expectDeclaration, actualDeclaration, languageVersionSettings)?.let { return it }
 
             expectDeclaration is EnumEntrySymbolMarker && actualDeclaration is EnumEntrySymbolMarker -> {
                 // do nothing, entries are matched only by name
@@ -558,6 +592,7 @@
         expectVisibility: Visibility,
         expectModality: Modality?,
         actualVisibility: Visibility,
+        languageVersionSettings: LanguageVersionSettings,
     ): Boolean {
         val compare = Visibilities.compare(expectVisibility, actualVisibility)
         return if (expectModality != Modality.FINAL) {
@@ -647,12 +682,13 @@
     private fun getPropertiesIncompatibility(
         expected: PropertySymbolMarker,
         actual: PropertySymbolMarker,
+        languageVersionSettings: LanguageVersionSettings,
     ): Incompatible.ExpectActualCheckingIncompatible<*>? {
         return when {
             !equalBy(expected, actual) { p -> p.isVar } -> Incompatible.PropertyKind
             !equalBy(expected, actual) { p -> p.isLateinit } -> Incompatible.PropertyLateinitModifier
             expected.isConst && !actual.isConst -> Incompatible.PropertyConstModifier
-            !arePropertySettersWithCompatibleVisibilities(expected, actual) -> Incompatible.PropertySetterVisibility
+            !arePropertySettersWithCompatibleVisibilities(expected, actual, languageVersionSettings) -> Incompatible.PropertySetterVisibility
             else -> null
         }
     }
@@ -661,10 +697,16 @@
     private fun arePropertySettersWithCompatibleVisibilities(
         expected: PropertySymbolMarker,
         actual: PropertySymbolMarker,
+        languageVersionSettings: LanguageVersionSettings
     ): 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,
+            languageVersionSettings
+        )
     }
 
     // ---------------------------------------- Utils ----------------------------------------
diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt
index c685677..cdc7465 100644
--- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt
+++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt
@@ -7,6 +7,7 @@
 
 import org.jetbrains.kotlin.descriptors.*
 import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualChecker
+import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualMatcher
 import org.jetbrains.kotlin.resolve.descriptorUtil.classId
 import org.jetbrains.kotlin.resolve.descriptorUtil.module
 import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Compatible
@@ -29,7 +30,7 @@
                             // TODO: support non-source definitions (e.g. from Java)
                             actual.couldHaveASource
                 }.groupBy { actual ->
-                    AbstractExpectActualChecker.getCallablesCompatibility(
+                    AbstractExpectActualMatcher.getCallablesCompatibility(
                         expected,
                         actual,
                         parentSubstitutor = null,
@@ -43,7 +44,7 @@
                 context.findClassifiersFromModule(expected.classId, platformModule, moduleVisibilityFilter).filter { actual ->
                     expected != actual && !actual.isExpect && actual.couldHaveASource
                 }.groupBy { actual ->
-                    AbstractExpectActualChecker.getClassifiersCompatibility(
+                    AbstractExpectActualMatcher.getClassifiersCompatibility(
                         expected,
                         actual,
                         checkClassScopesCompatibility = true,