From 0ed0152ee0d6fa3617c5f723fe8d94679a8590df Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Tue, 21 Apr 2020 13:15:29 +0700 Subject: [PATCH] [Linker] Add option to control scope of DescriptorByIdSignatureFinder Currently DescriptorByIdSignatureFinder performs lookup of descriptor not only in the given module but also in its dependencies. This behaviour is incorrect if we have some kind of relation (e.g. mapping) between moduleDescriptor and found descriptor. Thus, we add a handle to control search scope. --- .../DescriptorByIdSignatureFinder.kt | 52 +++++++++++++++++-- .../backend/jvm/serialization/JvmIrLinker.kt | 5 +- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt index 4b50acd5f36..8bbf6747544 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt @@ -6,10 +6,34 @@ package org.jetbrains.kotlin.backend.common.serialization import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.KotlinMangler -class DescriptorByIdSignatureFinder(private val moduleDescriptor: ModuleDescriptor, private val mangler: KotlinMangler.DescriptorMangler) { +class DescriptorByIdSignatureFinder( + private val moduleDescriptor: ModuleDescriptor, + private val mangler: KotlinMangler.DescriptorMangler, + private val lookupMode: LookupMode +) { + init { + assert(lookupMode != LookupMode.MODULE_ONLY || moduleDescriptor is ModuleDescriptorImpl) + } + + /** + * Sets search scope for [findDescriptorBySignature]. + */ + enum class LookupMode { + /** + * Perform search of descriptor in [moduleDescriptor] and its dependencies. + */ + MODULE_WITH_DEPENDENCIES, + + /** + * Perform search of descriptor only in [moduleDescriptor]. + */ + MODULE_ONLY + } + fun findDescriptorBySignature(signature: IdSignature): DeclarationDescriptor? = when (signature) { is IdSignature.AccessorSignature -> findDescriptorForAccessorSignature(signature) is IdSignature.PublicSignature -> findDescriptorForPublicSignature(signature) @@ -24,11 +48,29 @@ class DescriptorByIdSignatureFinder(private val moduleDescriptor: ModuleDescript } } + private fun performLookup(signature: IdSignature.PublicSignature): Collection { + val declarationName = signature.declarationFqn.pathSegments().first() + return when (lookupMode) { + LookupMode.MODULE_WITH_DEPENDENCIES -> { + moduleDescriptor + .getPackage(signature.packageFqName()) + .memberScope + .getContributedDescriptors { name -> name == declarationName } + } + LookupMode.MODULE_ONLY -> { + (moduleDescriptor as ModuleDescriptorImpl) + .packageFragmentProviderForModuleContentWithoutDependencies + .getPackageFragments(signature.packageFqName()) + .map { it.getMemberScope() } + .flatMap { it.getContributedDescriptors { name -> name == declarationName } } + } + } + } + private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? { - val packageDescriptor = moduleDescriptor.getPackage(signature.packageFqName()) + val toplevelDescriptors = performLookup(signature) + .ifEmpty { return null } val pathSegments = signature.declarationFqn.pathSegments() - val toplevelDescriptors = packageDescriptor.memberScope.getContributedDescriptors { name -> name == pathSegments.first() } - .filter { it.name == pathSegments.first() } val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current -> acc.flatMap { container -> val classDescriptor = container as? ClassDescriptor @@ -50,7 +92,7 @@ class DescriptorByIdSignatureFinder(private val moduleDescriptor: ModuleDescript } } - private fun findDescriptorByHash(candidates: List, id: Long?): DeclarationDescriptor? = + private fun findDescriptorByHash(candidates: Collection, id: Long?): DeclarationDescriptor? = candidates.firstOrNull { candidate -> if (id == null) { // We don't compute id for typealiases and classes. diff --git a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/ir/backend/jvm/serialization/JvmIrLinker.kt b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/ir/backend/jvm/serialization/JvmIrLinker.kt index e77b522bb67..c4af7a5c00c 100644 --- a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/ir/backend/jvm/serialization/JvmIrLinker.kt +++ b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/ir/backend/jvm/serialization/JvmIrLinker.kt @@ -111,7 +111,10 @@ class JvmIrLinker(currentModule: ModuleDescriptor?, logger: LoggingContext, buil // TODO: implement proper check whether `idSig` belongs to this module override fun contains(idSig: IdSignature): Boolean = true - private val descriptorFinder = DescriptorByIdSignatureFinder(moduleDescriptor, manglerDesc) + private val descriptorFinder = DescriptorByIdSignatureFinder( + moduleDescriptor, manglerDesc, + DescriptorByIdSignatureFinder.LookupMode.MODULE_ONLY + ) private fun resolveDescriptor(idSig: IdSignature): DeclarationDescriptor { return descriptorFinder.findDescriptorBySignature(idSig) ?: error("No descriptor found for $idSig")