WIP! Tue 3 Oct 17:51:28 CEST 2023
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt index ad02db5..1e7d7a4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt
@@ -185,7 +185,8 @@ classTypeSubstitutor, expect, actual, - matchingContext + matchingContext, + context.languageVersionSettings ) } .takeIf { kinds -> kinds.all { it != ExpectActualCompatibility.Compatible } }
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 36700f6..2233723 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
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.mpp.CallableSymbolMarker import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualChecker +import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualMatcher import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.utils.zipIfSizesAreEqual @@ -69,7 +70,7 @@ candidates.filter { expectSymbol -> actualSymbol != expectSymbol && expectSymbol.isExpect }.groupBy { expectDeclaration -> - AbstractExpectActualChecker.getCallablesCompatibility( + AbstractExpectActualMatcher.getCallablesCompatibility( expectDeclaration, actualSymbol as CallableSymbolMarker, parentSubstitutor, @@ -88,13 +89,13 @@ is FirClassLikeSymbol<*> -> { val expectClassSymbol = useSiteSession.dependenciesSymbolProvider .getClassLikeSymbolByClassId(actualSymbol.classId) as? FirRegularClassSymbol ?: return emptyMap() - val compatibility = AbstractExpectActualChecker.getClassifiersCompatibility( - expectClassSymbol, - actualSymbol, - checkClassScopesCompatibility = true, - context - ) - mapOf(compatibility to listOf(expectClassSymbol)) + //val compatibility = AbstractExpectActualChecker.getClassifiersCompatibility( + // expectClassSymbol, + // actualSymbol, + // checkClassScopesCompatibility = true, + // context + //) + mapOf((ExpectActualCompatibility.Compatible as ExpectActualCompatibility<FirBasedSymbol<*>>) to listOf(expectClassSymbol)) } else -> emptyMap() }
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt index 079c576..dee1c53 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt
@@ -6,6 +6,7 @@ package org.jetbrains.kotlin.resolve.checkers import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -70,7 +71,7 @@ declaration: KtClassLikeDeclaration, descriptor: ClassifierDescriptorWithTypeParameters, ) { - val scopeDiff = calculateExpectActualScopeDiff(expect, actual) + val scopeDiff = calculateExpectActualScopeDiff(expect, actual, context.languageVersionSettings) if (scopeDiff.isNotEmpty()) { context.trace.report( Errors.ACTUAL_CLASSIFIER_MUST_HAVE_THE_SAME_MEMBERS_AS_NON_FINAL_EXPECT_CLASSIFIER_WARNING.on( @@ -164,7 +165,8 @@ classTypeSubstitutor, expect, actual, - matchingContext + matchingContext, + languageVersionSettings ) } .takeIf { kinds -> kinds.all { it != K1ExpectActualCompatibility.Compatible } }
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 12ec28e..8d3628f 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.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,7 +22,7 @@ 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.calls.mpp.AbstractExpectActualMatcher import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import java.io.File @@ -219,7 +221,7 @@ actualSymbols: List<IrSymbol>, context: MatchingContext ) { - AbstractExpectActualChecker.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals( + AbstractExpectActualMatcher.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals( expectSymbol, actualSymbols, context,
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 8b4bdce..35179f1 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
@@ -21,6 +21,7 @@ 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,7 +46,7 @@ matchingActuals += actualSymbol } } - AbstractExpectActualChecker.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals( + AbstractExpectActualMatcher.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals( expectSymbol, actualSymbols, context
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.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualMatcher.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualMatcher.kt index aefa806..82fe4b2 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
@@ -8,7 +8,6 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.mpp.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames @@ -24,18 +23,18 @@ import java.util.* object AbstractExpectActualMatcher { - fun <T : DeclarationSymbolMarker> getClassifiersCompatibility( - expectClassSymbol: RegularClassSymbolMarker, - actualClassLikeSymbol: ClassLikeSymbolMarker, - checkClassScopesCompatibility: Boolean, - context: ExpectActualMatchingContext<T>, - ): ExpectActualCompatibility<T> { - val result = with(context) { - getClassifiersCompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor = null, checkClassScopesCompatibility) - } - @Suppress("UNCHECKED_CAST") - return result as ExpectActualCompatibility<T> - } + //fun <T : DeclarationSymbolMarker> getClassifiersCompatibility( + // expectClassSymbol: RegularClassSymbolMarker, + // actualClassLikeSymbol: ClassLikeSymbolMarker, + // checkClassScopesCompatibility: Boolean, + // context: ExpectActualMatchingContext<T>, + //): ExpectActualCompatibility<T> { + // val result = with(context) { + // getClassifiersCompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor = null, checkClassScopesCompatibility) + // } + // @Suppress("UNCHECKED_CAST") + // return result as ExpectActualCompatibility<T> + //} fun <T : DeclarationSymbolMarker> getCallablesCompatibility( expectDeclaration: CallableSymbolMarker, @@ -70,95 +69,95 @@ } } - context(ExpectActualMatchingContext<*>) - @Suppress("warnings") - private fun getClassifiersCompatibility( - expectClassSymbol: RegularClassSymbolMarker, - actualClassLikeSymbol: ClassLikeSymbolMarker, - parentSubstitutor: TypeSubstitutorMarker?, - checkClassScopes: Boolean, - ): ExpectActualCompatibility<*> = getClassifiersIncompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor, checkClassScopes) - ?: ExpectActualCompatibility.Compatible + //context(ExpectActualMatchingContext<*>) + //@Suppress("warnings") + //private fun getClassifiersCompatibility( + // expectClassSymbol: RegularClassSymbolMarker, + // actualClassLikeSymbol: ClassLikeSymbolMarker, + // parentSubstitutor: TypeSubstitutorMarker?, + // checkClassScopes: Boolean, + //): ExpectActualCompatibility<*> = getClassifiersIncompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor, checkClassScopes) + // ?: ExpectActualCompatibility.Compatible - context(ExpectActualMatchingContext<*>) - @Suppress("warnings") - private fun getClassifiersIncompatibility( - expectClassSymbol: RegularClassSymbolMarker, - actualClassLikeSymbol: ClassLikeSymbolMarker, - parentSubstitutor: TypeSubstitutorMarker?, - checkClassScopesCompatibility: Boolean, - ): 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) { - "This function should be invoked only for declarations with the same name: $expectClassSymbol, $actualClassLikeSymbol" - } + //context(ExpectActualMatchingContext<*>) + //@Suppress("warnings") + //private fun getClassifiersIncompatibility( + // expectClassSymbol: RegularClassSymbolMarker, + // actualClassLikeSymbol: ClassLikeSymbolMarker, + // parentSubstitutor: TypeSubstitutorMarker?, + // checkClassScopesCompatibility: Boolean, + //): 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) { + // "This function should be invoked only for declarations with the same name: $expectClassSymbol, $actualClassLikeSymbol" + // } + // + // val actualClass = when (actualClassLikeSymbol) { + // is RegularClassSymbolMarker -> actualClassLikeSymbol + // is TypeAliasSymbolMarker -> actualClassLikeSymbol.expandToRegularClass() + // ?: return null // do not report extra error on erroneous typealias + // else -> error("Incorrect actual classifier for $expectClassSymbol: $actualClassLikeSymbol") + // } + // + // if (!areCompatibleClassKinds(expectClassSymbol, actualClass)) return Incompatible.ClassKind + // + // if (!equalBy(expectClassSymbol, actualClass) { listOf(it.isCompanion, it.isInner, it.isInline || it.isValue) }) { + // return Incompatible.ClassModifiers + // } + // + // if (expectClassSymbol.isFun && !actualClass.isFun && actualClass.isNotSamInterface()) { + // return Incompatible.FunInterfaceModifier + // } + // + // val expectTypeParameterSymbols = expectClassSymbol.typeParameters + // val actualTypeParameterSymbols = actualClass.typeParameters + // if (expectTypeParameterSymbols.size != actualTypeParameterSymbols.size) { + // return Incompatible.ClassTypeParameterCount + // } + // + // if (!areCompatibleModalities(expectClassSymbol.modality, actualClass.modality)) { + // return Incompatible.Modality + // } + // + // if (!areCompatibleClassVisibilities(expectClassSymbol, actualClass)) { + // return Incompatible.Visibility + // } + // + // val substitutor = createExpectActualTypeParameterSubstitutor( + // (expectTypeParameterSymbols zipIfSizesAreEqual actualTypeParameterSymbols) + // ?: error("expect/actual type parameters sizes are checked earlier"), + // parentSubstitutor + // ) + // + // if (!areCompatibleTypeParameterUpperBounds(expectTypeParameterSymbols, actualTypeParameterSymbols, substitutor)) { + // return Incompatible.ClassTypeParameterUpperBounds + // } + // + // getTypeParametersVarianceOrReifiedIncompatibility(expectTypeParameterSymbols, actualTypeParameterSymbols) + // ?.let { return it } + // + // if (!areCompatibleSupertypes(expectClassSymbol, actualClass, substitutor)) { + // return Incompatible.Supertypes + // } + // + // if (checkClassScopesCompatibility) { + // getClassScopesIncompatibility(expectClassSymbol, actualClass, substitutor)?.let { return it } + // } + // + // return null + //} - val actualClass = when (actualClassLikeSymbol) { - is RegularClassSymbolMarker -> actualClassLikeSymbol - is TypeAliasSymbolMarker -> actualClassLikeSymbol.expandToRegularClass() - ?: return null // do not report extra error on erroneous typealias - else -> error("Incorrect actual classifier for $expectClassSymbol: $actualClassLikeSymbol") - } - - if (!areCompatibleClassKinds(expectClassSymbol, actualClass)) return Incompatible.ClassKind - - if (!equalBy(expectClassSymbol, actualClass) { listOf(it.isCompanion, it.isInner, it.isInline || it.isValue) }) { - return Incompatible.ClassModifiers - } - - if (expectClassSymbol.isFun && !actualClass.isFun && actualClass.isNotSamInterface()) { - return Incompatible.FunInterfaceModifier - } - - val expectTypeParameterSymbols = expectClassSymbol.typeParameters - val actualTypeParameterSymbols = actualClass.typeParameters - if (expectTypeParameterSymbols.size != actualTypeParameterSymbols.size) { - return Incompatible.ClassTypeParameterCount - } - - if (!areCompatibleModalities(expectClassSymbol.modality, actualClass.modality)) { - return Incompatible.Modality - } - - if (!areCompatibleClassVisibilities(expectClassSymbol, actualClass)) { - return Incompatible.Visibility - } - - val substitutor = createExpectActualTypeParameterSubstitutor( - (expectTypeParameterSymbols zipIfSizesAreEqual actualTypeParameterSymbols) - ?: error("expect/actual type parameters sizes are checked earlier"), - parentSubstitutor - ) - - if (!areCompatibleTypeParameterUpperBounds(expectTypeParameterSymbols, actualTypeParameterSymbols, substitutor)) { - return Incompatible.ClassTypeParameterUpperBounds - } - - getTypeParametersVarianceOrReifiedIncompatibility(expectTypeParameterSymbols, actualTypeParameterSymbols) - ?.let { return it } - - if (!areCompatibleSupertypes(expectClassSymbol, actualClass, substitutor)) { - return Incompatible.Supertypes - } - - if (checkClassScopesCompatibility) { - getClassScopesIncompatibility(expectClassSymbol, actualClass, substitutor)?.let { return it } - } - - return null - } - - context(ExpectActualMatchingContext<*>) - private fun areCompatibleSupertypes( - expectClassSymbol: RegularClassSymbolMarker, - actualClassSymbol: RegularClassSymbolMarker, - substitutor: TypeSubstitutorMarker, - ): Boolean { - return when (allowTransitiveSupertypesActualization) { - false -> areCompatibleSupertypesOneByOne(expectClassSymbol, actualClassSymbol, substitutor) - true -> areCompatibleSupertypesTransitive(expectClassSymbol, actualClassSymbol, substitutor) - } - } + //context(ExpectActualMatchingContext<*>) + //private fun areCompatibleSupertypes( + // expectClassSymbol: RegularClassSymbolMarker, + // actualClassSymbol: RegularClassSymbolMarker, + // substitutor: TypeSubstitutorMarker, + //): Boolean { + // return when (allowTransitiveSupertypesActualization) { + // false -> areCompatibleSupertypesOneByOne(expectClassSymbol, actualClassSymbol, substitutor) + // true -> areCompatibleSupertypesTransitive(expectClassSymbol, actualClassSymbol, substitutor) + // } + //} context(ExpectActualMatchingContext<*>) private fun areCompatibleSupertypesOneByOne( @@ -259,12 +258,13 @@ is RegularClassSymbolMarker -> { val parentSubstitutor = substitutor?.takeIf { !innerClassesCapturesOuterTypeParameters } - getClassifiersCompatibility( - expectMember, - actualMember as ClassLikeSymbolMarker, - parentSubstitutor, - checkClassScopesCompatibility, - ) + //getClassifiersCompatibility( + // expectMember, + // actualMember as ClassLikeSymbolMarker, + // parentSubstitutor, + // checkClassScopesCompatibility, + //) + ExpectActualCompatibility.Compatible } else -> error("Unsupported declaration: $expectMember ($actualMembers)") } @@ -316,13 +316,6 @@ // We must prioritize to return STRONG incompatible over WEAK incompatible (because STRONG incompatibility allows to search for overloads) return getCallablesStrongIncompatibility(expectDeclaration, actualDeclaration, parentSubstitutor) - ?: getCallablesWeakIncompatibility( - expectDeclaration, - actualDeclaration, - parentSubstitutor, - expectContainingClass, - actualContainingClass - ) ?: ExpectActualCompatibility.Compatible } @@ -380,104 +373,104 @@ return null } - context(ExpectActualMatchingContext<*>) - private fun getCallablesWeakIncompatibility( - expectDeclaration: CallableSymbolMarker, - actualDeclaration: CallableSymbolMarker, - parentSubstitutor: TypeSubstitutorMarker?, - expectContainingClass: RegularClassSymbolMarker?, - actualContainingClass: RegularClassSymbolMarker?, - ): Incompatible.ExpectActualCheckingIncompatible<*>? { - val expectedTypeParameters = expectDeclaration.typeParameters - val actualTypeParameters = actualDeclaration.typeParameters - val expectedValueParameters = expectDeclaration.valueParameters - val actualValueParameters = actualDeclaration.valueParameters - - if (shouldCheckReturnTypesOfCallables) { - val substitutor = createExpectActualTypeParameterSubstitutor( - (expectedTypeParameters zipIfSizesAreEqual actualTypeParameters) - ?: error("expect/actual type parameters sizes are checked earlier"), - parentSubstitutor - ) - - if (!areCompatibleExpectActualTypes(substitutor.safeSubstitute(expectDeclaration.returnType), actualDeclaration.returnType)) { - return Incompatible.ReturnType - } - } - - if (actualDeclaration.hasStableParameterNames && !equalsBy(expectedValueParameters, actualValueParameters) { it.name }) { - return Incompatible.ParameterNames - } - - if (!equalsBy(expectedTypeParameters, actualTypeParameters) { it.name }) { - return Incompatible.TypeParameterNames - } - - val expectModality = expectDeclaration.modality - val actualModality = actualDeclaration.modality - if ( - !areCompatibleModalities( - expectModality, - actualModality, - expectContainingClass?.modality, - actualContainingClass?.modality - ) - ) { - return Incompatible.Modality - } - - if (!areCompatibleCallableVisibilities(expectDeclaration.visibility, expectModality, actualDeclaration.visibility)) { - return Incompatible.Visibility - } - - getTypeParametersVarianceOrReifiedIncompatibility(expectedTypeParameters, actualTypeParameters)?.let { return it } - - if (shouldCheckAbsenceOfDefaultParamsInActual) { - // "Default parameters in actual" check is required only for functions, because only functions can have parameters - if (actualDeclaration is FunctionSymbolMarker && expectDeclaration is FunctionSymbolMarker) { - // Actual annotation constructors can have default argument values; their consistency with arguments in the expected annotation - // is checked in ExpectedActualDeclarationChecker.checkAnnotationConstructors - if (!actualDeclaration.isAnnotationConstructor() && - // If default params came from common supertypes of actual class and expect class then it's a valid code. - // Here we filter out such default params. - (actualDeclaration.allOverriddenDeclarationsRecursive() - expectDeclaration.allOverriddenDeclarationsRecursive().toSet()) - .flatMap { it.valueParameters }.any { it.hasDefaultValue } - ) { - return Incompatible.ActualFunctionWithDefaultParameters - } - } - } - - if (!equalsBy(expectedValueParameters, actualValueParameters) { it.isVararg }) { - return Incompatible.ValueParameterVararg - } - - // Adding noinline/crossinline to parameters is disallowed, except if the expected declaration was not inline at all - if (expectDeclaration is SimpleFunctionSymbolMarker && expectDeclaration.isInline) { - if (expectedValueParameters.indices.any { i -> !expectedValueParameters[i].isNoinline && actualValueParameters[i].isNoinline }) { - return Incompatible.ValueParameterNoinline - } - if (expectedValueParameters.indices.any { i -> !expectedValueParameters[i].isCrossinline && actualValueParameters[i].isCrossinline }) { - return Incompatible.ValueParameterCrossinline - } - } - - when { - expectDeclaration is FunctionSymbolMarker && actualDeclaration is FunctionSymbolMarker -> - getFunctionsIncompatibility(expectDeclaration, actualDeclaration)?.let { return it } - - expectDeclaration is PropertySymbolMarker && actualDeclaration is PropertySymbolMarker -> - getPropertiesIncompatibility(expectDeclaration, actualDeclaration)?.let { return it } - - expectDeclaration is EnumEntrySymbolMarker && actualDeclaration is EnumEntrySymbolMarker -> { - // do nothing, entries are matched only by name - } - - else -> error("Unsupported declarations: $expectDeclaration, $actualDeclaration") - } - - return null - } + //context(ExpectActualMatchingContext<*>) + //private fun getCallablesWeakIncompatibility( + // expectDeclaration: CallableSymbolMarker, + // actualDeclaration: CallableSymbolMarker, + // parentSubstitutor: TypeSubstitutorMarker?, + // expectContainingClass: RegularClassSymbolMarker?, + // actualContainingClass: RegularClassSymbolMarker?, + //): Incompatible.ExpectActualCheckingIncompatible<*>? { + // val expectedTypeParameters = expectDeclaration.typeParameters + // val actualTypeParameters = actualDeclaration.typeParameters + // val expectedValueParameters = expectDeclaration.valueParameters + // val actualValueParameters = actualDeclaration.valueParameters + // + // if (shouldCheckReturnTypesOfCallables) { + // val substitutor = createExpectActualTypeParameterSubstitutor( + // (expectedTypeParameters zipIfSizesAreEqual actualTypeParameters) + // ?: error("expect/actual type parameters sizes are checked earlier"), + // parentSubstitutor + // ) + // + // if (!areCompatibleExpectActualTypes(substitutor.safeSubstitute(expectDeclaration.returnType), actualDeclaration.returnType)) { + // return Incompatible.ReturnType + // } + // } + // + // if (actualDeclaration.hasStableParameterNames && !equalsBy(expectedValueParameters, actualValueParameters) { it.name }) { + // return Incompatible.ParameterNames + // } + // + // if (!equalsBy(expectedTypeParameters, actualTypeParameters) { it.name }) { + // return Incompatible.TypeParameterNames + // } + // + // val expectModality = expectDeclaration.modality + // val actualModality = actualDeclaration.modality + // if ( + // !areCompatibleModalities( + // expectModality, + // actualModality, + // expectContainingClass?.modality, + // actualContainingClass?.modality + // ) + // ) { + // return Incompatible.Modality + // } + // + // if (!areCompatibleCallableVisibilities(expectDeclaration.visibility, expectModality, actualDeclaration.visibility)) { + // return Incompatible.Visibility + // } + // + // getTypeParametersVarianceOrReifiedIncompatibility(expectedTypeParameters, actualTypeParameters)?.let { return it } + // + // if (shouldCheckAbsenceOfDefaultParamsInActual) { + // // "Default parameters in actual" check is required only for functions, because only functions can have parameters + // if (actualDeclaration is FunctionSymbolMarker && expectDeclaration is FunctionSymbolMarker) { + // // Actual annotation constructors can have default argument values; their consistency with arguments in the expected annotation + // // is checked in ExpectedActualDeclarationChecker.checkAnnotationConstructors + // if (!actualDeclaration.isAnnotationConstructor() && + // // If default params came from common supertypes of actual class and expect class then it's a valid code. + // // Here we filter out such default params. + // (actualDeclaration.allOverriddenDeclarationsRecursive() - expectDeclaration.allOverriddenDeclarationsRecursive().toSet()) + // .flatMap { it.valueParameters }.any { it.hasDefaultValue } + // ) { + // return Incompatible.ActualFunctionWithDefaultParameters + // } + // } + // } + // + // if (!equalsBy(expectedValueParameters, actualValueParameters) { it.isVararg }) { + // return Incompatible.ValueParameterVararg + // } + // + // // Adding noinline/crossinline to parameters is disallowed, except if the expected declaration was not inline at all + // if (expectDeclaration is SimpleFunctionSymbolMarker && expectDeclaration.isInline) { + // if (expectedValueParameters.indices.any { i -> !expectedValueParameters[i].isNoinline && actualValueParameters[i].isNoinline }) { + // return Incompatible.ValueParameterNoinline + // } + // if (expectedValueParameters.indices.any { i -> !expectedValueParameters[i].isCrossinline && actualValueParameters[i].isCrossinline }) { + // return Incompatible.ValueParameterCrossinline + // } + // } + // + // when { + // expectDeclaration is FunctionSymbolMarker && actualDeclaration is FunctionSymbolMarker -> + // getFunctionsIncompatibility(expectDeclaration, actualDeclaration)?.let { return it } + // + // expectDeclaration is PropertySymbolMarker && actualDeclaration is PropertySymbolMarker -> + // getPropertiesIncompatibility(expectDeclaration, actualDeclaration)?.let { return it } + // + // expectDeclaration is EnumEntrySymbolMarker && actualDeclaration is EnumEntrySymbolMarker -> { + // // do nothing, entries are matched only by name + // } + // + // else -> error("Unsupported declarations: $expectDeclaration, $actualDeclaration") + // } + // + // return null + //} context(ExpectActualMatchingContext<*>) private fun valueParametersCountCompatible( @@ -554,20 +547,20 @@ Modality.SEALED to enumSetOf(Modality.SEALED), ) - private fun areCompatibleCallableVisibilities( - expectVisibility: Visibility, - expectModality: Modality?, - actualVisibility: Visibility, - ): Boolean { - val compare = Visibilities.compare(expectVisibility, actualVisibility) - return if (expectModality != Modality.FINAL) { - // For overridable declarations visibility should match precisely, see KT-19664 - compare == 0 - } else { - // For non-overridable declarations actuals are allowed to have more permissive visibility - compare != null && compare <= 0 - } - } + //private fun areCompatibleCallableVisibilities( + // expectVisibility: Visibility, + // expectModality: Modality?, + // actualVisibility: Visibility, + //): Boolean { + // val compare = Visibilities.compare(expectVisibility, actualVisibility) + // return if (expectModality != Modality.FINAL) { + // // For overridable declarations visibility should match precisely, see KT-19664 + // compare == 0 + // } else { + // // For non-overridable declarations actuals are allowed to have more permissive visibility + // compare != null && compare <= 0 + // } + //} context(ExpectActualMatchingContext<*>) private fun areCompatibleClassVisibilities( @@ -623,49 +616,49 @@ return null } - context(ExpectActualMatchingContext<*>) - private fun getFunctionsIncompatibility( - expectFunction: CallableSymbolMarker, - actualFunction: CallableSymbolMarker, - ): Incompatible.ExpectActualCheckingIncompatible<*>? { - if (!equalBy(expectFunction, actualFunction) { f -> f.isSuspend }) { - return Incompatible.FunctionModifiersDifferent - } + //context(ExpectActualMatchingContext<*>) + //private fun getFunctionsIncompatibility( + // expectFunction: CallableSymbolMarker, + // actualFunction: CallableSymbolMarker, + //): Incompatible.ExpectActualCheckingIncompatible<*>? { + // if (!equalBy(expectFunction, actualFunction) { f -> f.isSuspend }) { + // return Incompatible.FunctionModifiersDifferent + // } + // + // if ( + // expectFunction.isInfix && !actualFunction.isInfix || + // expectFunction.isInline && !actualFunction.isInline || + // expectFunction.isOperator && !actualFunction.isOperator + // ) { + // return Incompatible.FunctionModifiersNotSubset + // } + // + // return null + //} - if ( - expectFunction.isInfix && !actualFunction.isInfix || - expectFunction.isInline && !actualFunction.isInline || - expectFunction.isOperator && !actualFunction.isOperator - ) { - return Incompatible.FunctionModifiersNotSubset - } + //context(ExpectActualMatchingContext<*>) + //private fun getPropertiesIncompatibility( + // expected: PropertySymbolMarker, + // actual: PropertySymbolMarker, + //): 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 + // else -> null + // } + //} - return null - } - - context(ExpectActualMatchingContext<*>) - private fun getPropertiesIncompatibility( - expected: PropertySymbolMarker, - actual: PropertySymbolMarker, - ): 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 - else -> null - } - } - - context(ExpectActualMatchingContext<*>) - private fun arePropertySettersWithCompatibleVisibilities( - expected: PropertySymbolMarker, - actual: PropertySymbolMarker, - ): Boolean { - val expectedSetter = expected.setter ?: return true - val actualSetter = actual.setter ?: return true - return areCompatibleCallableVisibilities(expectedSetter.visibility, expectedSetter.modality, actualSetter.visibility) - } + //context(ExpectActualMatchingContext<*>) + //private fun arePropertySettersWithCompatibleVisibilities( + // expected: PropertySymbolMarker, + // actual: PropertySymbolMarker, + //): Boolean { + // val expectedSetter = expected.setter ?: return true + // val actualSetter = actual.setter ?: return true + // return areCompatibleCallableVisibilities(expectedSetter.visibility, expectedSetter.modality, actualSetter.visibility) + //} // ---------------------------------------- Utils ----------------------------------------