[FE1.0] Optimize search of expect class member in annotation checker
In the following scenario, when we search corresponding expect member
for actual `A.B`, we can skip checking compatibility of `B` scope.
```
class A {
class B {
fun foo() {}
}
}
actual typealias AImpl = A
```
This is because:
1. Annotation checker runs no matter if found expect class is compatible
or not.
2. Class always has at most one corresponding `expect` class (unlike for
functions, which may have several overrides), so we are sure that we
found the right member.
^KT-60668
^KT-60936
This commit is contained in:
committed by
Space Team
parent
f1ea6545eb
commit
b57940a59b
+8
-1
@@ -154,7 +154,14 @@ object AbstractExpectActualAnnotationMatchChecker {
|
||||
if (skipCheckingAnnotationsOfActualClassMember(actualMember)) {
|
||||
continue
|
||||
}
|
||||
val expectToCompatibilityMap = findPotentialExpectClassMembersForActual(expectClass, actualClass, actualMember)
|
||||
val expectToCompatibilityMap = findPotentialExpectClassMembersForActual(
|
||||
expectClass, actualClass, actualMember,
|
||||
// Optimization: don't check class scopes, because:
|
||||
// 1. Annotation checker runs no matter if found expect class is compatible or not.
|
||||
// 2. Class always has at most one corresponding `expect` class (unlike for functions, which may have several overrides),
|
||||
// so we are sure that we found the right member.
|
||||
checkClassScopesCompatibility = false,
|
||||
)
|
||||
val expectMember = expectToCompatibilityMap.filter { it.value == ExpectActualCompatibility.Compatible }.keys.singleOrNull()
|
||||
// Check also incompatible members if only one is found
|
||||
?: expectToCompatibilityMap.keys.singleOrNull()
|
||||
|
||||
+17
-8
@@ -26,10 +26,11 @@ object AbstractExpectActualCompatibilityChecker {
|
||||
fun <T : DeclarationSymbolMarker> getClassifiersCompatibility(
|
||||
expectClassSymbol: RegularClassSymbolMarker,
|
||||
actualClassLikeSymbol: ClassLikeSymbolMarker,
|
||||
checkClassScopesCompatibility: Boolean,
|
||||
context: ExpectActualMatchingContext<T>,
|
||||
): ExpectActualCompatibility<T> {
|
||||
val result = with(context) {
|
||||
getClassifiersCompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor = null)
|
||||
getClassifiersCompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor = null, checkClassScopesCompatibility)
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return result as ExpectActualCompatibility<T>
|
||||
@@ -62,7 +63,8 @@ object AbstractExpectActualCompatibilityChecker {
|
||||
substitutor = null,
|
||||
expectClassSymbol = null,
|
||||
actualClassSymbol = null,
|
||||
unfulfilled = null
|
||||
unfulfilled = null,
|
||||
checkClassScopesCompatibility = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -73,7 +75,8 @@ object AbstractExpectActualCompatibilityChecker {
|
||||
expectClassSymbol: RegularClassSymbolMarker,
|
||||
actualClassLikeSymbol: ClassLikeSymbolMarker,
|
||||
parentSubstitutor: TypeSubstitutorMarker?,
|
||||
): ExpectActualCompatibility<*> = getClassifiersIncompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor)
|
||||
checkClassScopes: Boolean,
|
||||
): ExpectActualCompatibility<*> = getClassifiersIncompatibility(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor, checkClassScopes)
|
||||
?: ExpectActualCompatibility.Compatible
|
||||
|
||||
context(ExpectActualMatchingContext<*>)
|
||||
@@ -81,7 +84,8 @@ object AbstractExpectActualCompatibilityChecker {
|
||||
private fun getClassifiersIncompatibility(
|
||||
expectClassSymbol: RegularClassSymbolMarker,
|
||||
actualClassLikeSymbol: ClassLikeSymbolMarker,
|
||||
parentSubstitutor: TypeSubstitutorMarker?
|
||||
parentSubstitutor: TypeSubstitutorMarker?,
|
||||
checkClassScopesCompatibility: Boolean,
|
||||
): ExpectActualCompatibility.Incompatible.WeakIncompatible<*>? {
|
||||
// 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) {
|
||||
@@ -136,7 +140,9 @@ object AbstractExpectActualCompatibilityChecker {
|
||||
return Incompatible.Supertypes
|
||||
}
|
||||
|
||||
getClassScopesIncompatibility(expectClassSymbol, actualClass, substitutor)?.let { return it }
|
||||
if (checkClassScopesCompatibility) {
|
||||
getClassScopesIncompatibility(expectClassSymbol, actualClass, substitutor)?.let { return it }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -211,7 +217,8 @@ object AbstractExpectActualCompatibilityChecker {
|
||||
substitutor,
|
||||
expectClassSymbol,
|
||||
actualClassSymbol,
|
||||
unfulfilled
|
||||
unfulfilled,
|
||||
checkClassScopesCompatibility = true,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -236,7 +243,8 @@ object AbstractExpectActualCompatibilityChecker {
|
||||
substitutor: TypeSubstitutorMarker?,
|
||||
expectClassSymbol: RegularClassSymbolMarker?,
|
||||
actualClassSymbol: RegularClassSymbolMarker?,
|
||||
unfulfilled: MutableList<Pair<DeclarationSymbolMarker, Map<Incompatible<*>, List<DeclarationSymbolMarker?>>>>?
|
||||
unfulfilled: MutableList<Pair<DeclarationSymbolMarker, Map<Incompatible<*>, List<DeclarationSymbolMarker?>>>>?,
|
||||
checkClassScopesCompatibility: Boolean,
|
||||
) {
|
||||
val mapping = actualMembers.keysToMap { actualMember ->
|
||||
when (expectMember) {
|
||||
@@ -253,7 +261,8 @@ object AbstractExpectActualCompatibilityChecker {
|
||||
getClassifiersCompatibility(
|
||||
expectMember,
|
||||
actualMember as ClassLikeSymbolMarker,
|
||||
parentSubstitutor
|
||||
parentSubstitutor,
|
||||
checkClassScopesCompatibility,
|
||||
)
|
||||
}
|
||||
else -> error("Unsupported declaration: $expectMember ($actualMembers)")
|
||||
|
||||
+1
@@ -210,5 +210,6 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
||||
expectClass: RegularClassSymbolMarker,
|
||||
actualClass: RegularClassSymbolMarker,
|
||||
actualMember: DeclarationSymbolMarker,
|
||||
checkClassScopesCompatibility: Boolean,
|
||||
): Map<out DeclarationSymbolMarker, ExpectActualCompatibility<*>>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user