[FIR, IR] Convert FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker into ExpectActualCheckingCompatibility

FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker is an adhoc
checker which can be converted to ExpectActualCheckingCompatibility to
reuse common expect-actual checking infrastructure.

^KT-62913 Fixed
Review: https://jetbrains.team/p/kt/reviews/13094/timeline

Tests that were broken by one of my previous commits are now fixed:
- actualFakeOverride_paramsAreCompatibleViaSharedMethodWithDefaultParams.kt
- inheritedJavaMembers.kt

DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE diagnostic
disappeared in delegation.fir.kt because only one
AbstractExpectActualChecker incompatibility can be reported at a time
(DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE is now reported
not by adhoc checker but by common AbstractExpectActualChecker). It
would be nice to report both of them, but it's a separate issue KT-62631

delegation2 test makes sure that
DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE is reported when
NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS is fixed
This commit is contained in:
Nikita Bobko
2023-11-17 11:39:24 +01:00
committed by teamcity
parent c8a9928624
commit 7166adb179
20 changed files with 156 additions and 152 deletions
@@ -369,19 +369,31 @@ object AbstractExpectActualChecker {
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 ExpectActualCheckingCompatibility.ActualFunctionWithDefaultParameters
}
if (shouldCheckDefaultParams &&
// "parameters" checks are required only for functions, because only functions can have parameters
actualDeclaration is FunctionSymbolMarker && expectDeclaration is FunctionSymbolMarker
) {
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitDefaultArgumentsInExpectActualizedByFakeOverride) &&
(actualDeclaration.isFakeOverride(actualContainingClass) || actualDeclaration.isDelegatedMember) &&
// 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.
(expectDeclaration.allRecursivelyOverriddenDeclarationsIncludingSelf() -
actualDeclaration.allRecursivelyOverriddenDeclarationsIncludingSelf().toSet())
.flatMap { it.valueParameters }.any { it.hasDefaultValueNonRecursive }
) {
return ExpectActualCheckingCompatibility.DefaultArgumentsInExpectActualizedByFakeOverride
}
// 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.allRecursivelyOverriddenDeclarationsIncludingSelf() -
expectDeclaration.allRecursivelyOverriddenDeclarationsIncludingSelf().toSet())
.flatMap { it.valueParameters }.any { it.hasDefaultValue }
) {
return ExpectActualCheckingCompatibility.ActualFunctionWithDefaultParameters
}
}
@@ -74,36 +74,6 @@ object AbstractExpectActualMatcher {
ExpectActualMatchingCompatibility.MatchedSuccessfully
}
fun recursivelyMatchClassScopes( // todo drop KT-62913
expectClassSymbol: RegularClassSymbolMarker,
actualClassSymbol: RegularClassSymbolMarker,
context: ExpectActualMatchingContext<*>,
): Unit = with(context) {
val expectTypeParameterSymbols = expectClassSymbol.typeParameters
val actualTypeParameterSymbols = actualClassSymbol.typeParameters
val substitutor = createExpectActualTypeParameterSubstitutor(
(expectTypeParameterSymbols zipIfSizesAreEqual actualTypeParameterSymbols) ?: return,
parentSubstitutor = null,
)
val actualMembersByName = actualClassSymbol.collectAllMembers(isActualDeclaration = true).groupBy { it.name }
outer@ for (expectMember in expectClassSymbol.collectAllMembers(isActualDeclaration = false)) {
val actualMembers = getPossibleActualsByExpectName(expectMember, actualMembersByName)
matchSingleExpectAgainstPotentialActuals(
expectMember,
actualMembers,
substitutor,
expectClassSymbol,
actualClassSymbol,
mismatchedMembers = null,
)
}
// TODO: check static scope?
}
/**
* Besides returning the matched declaration
*
@@ -40,7 +40,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
// Known clients that do suppress:
// - stdlib
// - coroutines
val shouldCheckAbsenceOfDefaultParamsInActual: Boolean
val shouldCheckDefaultParams: Boolean
/**
* This flag determines, how visibilities for classes/typealiases will be matched
@@ -123,9 +123,9 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
val FunctionSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
/**
* Returns all symbols that are overridden by [this] symbol
* Returns all symbols that are overridden by [this] symbol, including self
*/
fun FunctionSymbolMarker.allOverriddenDeclarationsRecursive(): Sequence<CallableSymbolMarker>
fun FunctionSymbolMarker.allRecursivelyOverriddenDeclarationsIncludingSelf(): Sequence<CallableSymbolMarker>
val CallableSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
get() = (this as? FunctionSymbolMarker)?.valueParameters ?: emptyList()
@@ -134,6 +134,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
val ValueParameterSymbolMarker.isNoinline: Boolean
val ValueParameterSymbolMarker.isCrossinline: Boolean
val ValueParameterSymbolMarker.hasDefaultValue: Boolean
val ValueParameterSymbolMarker.hasDefaultValueNonRecursive: Boolean
fun CallableSymbolMarker.isAnnotationConstructor(): Boolean
@@ -158,6 +159,8 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
fun CallableSymbolMarker.isFakeOverride(containingExpectClass: RegularClassSymbolMarker?): Boolean
val CallableSymbolMarker.isDelegatedMember: Boolean
val CallableSymbolMarker.hasStableParameterNames: Boolean
fun onMatchedMembers(