From d614f06259741ab996dc58902f37f0b050e38eb4 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Fri, 4 Aug 2023 13:04:55 +0200 Subject: [PATCH] [FE 1.0] Refactor: extract logic of matching actual against potential expects Will be needed in subsequent commits for the annotation checker. `findExpectForActual` is not suitable for the checker because `findExpectForActual` searches expect class with same `ClassId` for actual class containing current member (see method `findClassifiersFromModule`), which is: 1. Unnecessary, since we already have expect class in annotation checker 2. Incorrect when class actualized via typealias and `ClassId` is different. So, it is needed to extract logic of searching potential expects for actual member and already known expect class. ^KT-60668 ^KT-60936 --- .../multiplatform/ExpectedActualResolver.kt | 98 +++++++++++-------- 1 file changed, 58 insertions(+), 40 deletions(-) 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 a2370924baa..bd13cd4cc22 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt @@ -77,53 +77,71 @@ object ExpectedActualResolver { else -> return null // do not report anything for incorrect code, e.g. 'actual' local function } - candidates.filter { declaration -> - actual != declaration && declaration.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && declaration.isExpect - }.groupBy { declaration -> - // TODO: optimize by caching this per actual-expected class pair, do not create a new substitutor for each actual member - var expectedClass: ClassDescriptor? = null - var actualClass: ClassDescriptor? = null - val substitutor = - when (container) { - is ClassDescriptor -> { - actualClass = container - expectedClass = declaration.containingDeclaration as ClassDescriptor - // TODO: this might not work for members of inner generic classes - runIf(expectedClass.declaredTypeParameters.size == container.declaredTypeParameters.size) { - context.createExpectActualTypeParameterSubstitutor( - expectedClass.declaredTypeParameters, - container.declaredTypeParameters, - parentSubstitutor = null - ) - } - } - else -> null - } - AbstractExpectActualCompatibilityChecker.getCallablesCompatibility( - expectDeclaration = declaration, - actualDeclaration = actual, - parentSubstitutor = substitutor, - expectContainingClass = expectedClass, - actualContainingClass = actualClass, - context - ) - } + matchActualCallableAgainstPotentialExpects(actual, candidates, container, context) } is ClassifierDescriptorWithTypeParameters -> { - context.findClassifiersFromModule(actual.classId, actual.module, moduleFilter).filter { declaration -> - actual != declaration && declaration is ClassDescriptor && declaration.isExpect - }.groupBy { expected -> - AbstractExpectActualCompatibilityChecker.getClassifiersCompatibility( - expected as ClassDescriptor, - actual, - context - ) - } + val candidates = context.findClassifiersFromModule(actual.classId, actual.module, moduleFilter) + matchActualClassAgainstPotentialExpects(actual, candidates, context) } else -> null } } + private fun matchActualCallableAgainstPotentialExpects( + actual: CallableMemberDescriptor, + candidates: Collection, + container: DeclarationDescriptor, + context: ClassicExpectActualMatchingContext, + ): Map, List> { + return candidates.filter { declaration -> + actual != declaration && declaration.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && declaration.isExpect + }.groupBy { declaration -> + // TODO: optimize by caching this per actual-expected class pair, do not create a new substitutor for each actual member + var expectedClass: ClassDescriptor? = null + var actualClass: ClassDescriptor? = null + val substitutor = + when (container) { + is ClassDescriptor -> { + actualClass = container + expectedClass = declaration.containingDeclaration as ClassDescriptor + // TODO: this might not work for members of inner generic classes + runIf(expectedClass.declaredTypeParameters.size == container.declaredTypeParameters.size) { + context.createExpectActualTypeParameterSubstitutor( + expectedClass.declaredTypeParameters, + container.declaredTypeParameters, + parentSubstitutor = null + ) + } + } + else -> null + } + AbstractExpectActualCompatibilityChecker.getCallablesCompatibility( + expectDeclaration = declaration, + actualDeclaration = actual, + parentSubstitutor = substitutor, + expectContainingClass = expectedClass, + actualContainingClass = actualClass, + context + ) + } + } + + private fun matchActualClassAgainstPotentialExpects( + actual: ClassifierDescriptorWithTypeParameters, + candidates: Collection, + context: ClassicExpectActualMatchingContext, + ): Map, List> { + return candidates.filter { declaration -> + actual != declaration && declaration is ClassDescriptor && declaration.isExpect + }.groupBy { expected -> + AbstractExpectActualCompatibilityChecker.getClassifiersCompatibility( + expected as ClassDescriptor, + actual, + context + ) + } + } + private fun CallableMemberDescriptor.findNamesakesFromModule( context: ClassicExpectActualMatchingContext, module: ModuleDescriptor,