[MPP] Introduce allModulesProviding(Expects|Actuals)For filters

This new filters will also take care of filtering out descriptors
that are provided by 'regular' dependencies instead of 'dependsOn'
dependencies.

^KT-50120
This commit is contained in:
sebastian.sellmair
2021-12-20 15:09:51 +01:00
committed by Space
parent d1ce7ae870
commit 2e55b82ba3
10 changed files with 57 additions and 55 deletions
+1
View File
@@ -1,6 +1,7 @@
<component name="ProjectDictionaryState"> <component name="ProjectDictionaryState">
<dictionary name="sebastiansellmair"> <dictionary name="sebastiansellmair">
<words> <words>
<w>actuals</w>
<w>cinterops</w> <w>cinterops</w>
<w>instantiator</w> <w>instantiator</w>
<w>interops</w> <w>interops</w>
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver import org.jetbrains.kotlin.resolve.multiplatform.findCompatibleExpectsForActual
import org.jetbrains.kotlin.resolve.multiplatform.onlyFromThisModule import org.jetbrains.kotlin.resolve.multiplatform.onlyFromThisModule
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.getExceptionMessage import org.jetbrains.kotlin.util.getExceptionMessage
@@ -182,9 +182,7 @@ object CodegenUtil {
@JvmStatic @JvmStatic
fun findExpectedFunctionForActual(descriptor: FunctionDescriptor): FunctionDescriptor? { fun findExpectedFunctionForActual(descriptor: FunctionDescriptor): FunctionDescriptor? {
val compatibleExpectedFunctions = with(ExpectedActualResolver) { val compatibleExpectedFunctions = descriptor.findCompatibleExpectsForActual(onlyFromThisModule(descriptor.module))
descriptor.findCompatibleExpectedForActual(onlyFromThisModule(descriptor.module))
}
return compatibleExpectedFunctions.firstOrNull() as FunctionDescriptor? return compatibleExpectedFunctions.firstOrNull() as FunctionDescriptor?
} }
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.codegen package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver import org.jetbrains.kotlin.resolve.multiplatform.findCompatibleActualsForExpected
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
/** /**
@@ -29,9 +29,7 @@ class FrameMapWithExpectActualSupport(private val module: ModuleDescriptor) : Fr
// in ExpressionCodegen.generateThisOrOuterFromContext by comparing classes by type constructor equality. // in ExpressionCodegen.generateThisOrOuterFromContext by comparing classes by type constructor equality.
if (parameter !is ReceiverParameterDescriptor || parameter.value !is ExtensionReceiver) return null if (parameter !is ReceiverParameterDescriptor || parameter.value !is ExtensionReceiver) return null
val actual = with(ExpectedActualResolver) { val actual = container.findCompatibleActualsForExpected(module).firstOrNull()
container.findCompatibleActualForExpected(module).firstOrNull()
}
return (actual as? CallableDescriptor)?.extensionReceiverParameter return (actual as? CallableDescriptor)?.extensionReceiverParameter
} }
@@ -44,7 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker; import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil; import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver; import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolverKt;
import org.jetbrains.kotlin.resolve.scopes.*; import org.jetbrains.kotlin.resolve.scopes.*;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt; import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.*;
@@ -532,7 +532,7 @@ public class BodyResolver {
} }
parentEnumOrSealed.add(currentDescriptor.getTypeConstructor()); parentEnumOrSealed.add(currentDescriptor.getTypeConstructor());
if (currentDescriptor.isExpect()) { if (currentDescriptor.isExpect()) {
List<MemberDescriptor> actualDescriptors = ExpectedActualResolver.INSTANCE.findCompatibleActualForExpected( List<MemberDescriptor> actualDescriptors = ExpectedActualResolverKt.findCompatibleActualsForExpected(
currentDescriptor, DescriptorUtilsKt.getModule( currentDescriptor) currentDescriptor, DescriptorUtilsKt.getModule( currentDescriptor)
); );
for (MemberDescriptor actualDescriptor: actualDescriptors) { for (MemberDescriptor actualDescriptor: actualDescriptors) {
@@ -23,9 +23,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver import org.jetbrains.kotlin.resolve.multiplatform.*
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.resolve.multiplatform.onlyFromThisModule
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
// `doRemove` means should expect-declaration be removed from IR // `doRemove` means should expect-declaration be removed from IR
@@ -136,16 +134,13 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
private fun MemberDescriptor.findActualForExpect(): MemberDescriptor? { private fun MemberDescriptor.findActualForExpect(): MemberDescriptor? {
if (!isExpect) error(this) if (!isExpect) error(this)
return with(ExpectedActualResolver) { return findCompatibleActualsForExpected(module).singleOrNull()
findCompatibleActualForExpected(this@findActualForExpect.module).singleOrNull()
}
} }
private fun MemberDescriptor.findExpectForActual(): MemberDescriptor? { private fun MemberDescriptor.findExpectForActual(): MemberDescriptor? {
if (!isActual) error(this) if (!isActual) error(this)
return with(ExpectedActualResolver) { return findCompatibleExpectsForActual().singleOrNull()
findCompatibleExpectedForActual(onlyFromThisModule(this@findExpectForActual.module)).singleOrNull()
}
} }
private fun IrExpression.remapExpectValueSymbols(): IrExpression { private fun IrExpression.remapExpectValueSymbols(): IrExpression {
@@ -26,8 +26,7 @@ import org.jetbrains.kotlin.resolve.calls.model.CollectionLiteralKotlinCallArgum
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
import org.jetbrains.kotlin.resolve.multiplatform.ALL_MODULES import org.jetbrains.kotlin.resolve.multiplatform.findCompatibleExpectsForActual
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
@@ -112,10 +111,8 @@ fun ValueParameterDescriptor.hasDefaultValue(): Boolean {
private fun ValueParameterDescriptor.checkExpectedParameter(checker: (ValueParameterDescriptor) -> Boolean): Boolean { private fun ValueParameterDescriptor.checkExpectedParameter(checker: (ValueParameterDescriptor) -> Boolean): Boolean {
val function = containingDeclaration val function = containingDeclaration
if (function is FunctionDescriptor && function.isActual) { if (function is FunctionDescriptor && function.isActual) {
with(ExpectedActualResolver) { val expected = function.findCompatibleExpectsForActual().firstOrNull()
val expected = function.findCompatibleExpectedForActual(ALL_MODULES).firstOrNull() return expected is FunctionDescriptor && checker(expected.valueParameters[index])
return expected is FunctionDescriptor && checker(expected.valueParameters[index])
}
} }
return false return false
} }
@@ -24,24 +24,11 @@ import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.keysToMap import org.jetbrains.kotlin.utils.keysToMap
object ExpectedActualResolver { object ExpectedActualResolver {
// FIXME(dsavvinov): review clients, as they won't work properly in HMPP projects
fun MemberDescriptor.findCompatibleActualForExpected(platformModule: ModuleDescriptor): List<MemberDescriptor> =
findActualForExpected(this, platformModule, onlyFromThisModule(platformModule))?.get(Compatible).orEmpty()
fun MemberDescriptor.findAnyActualForExpected(platformModule: ModuleDescriptor): List<MemberDescriptor> {
val actualsGroupedByCompatibility = findActualForExpected(this, platformModule, onlyFromThisModule(platformModule))
return actualsGroupedByCompatibility?.get(Compatible)
?: actualsGroupedByCompatibility?.values?.flatten()
?: emptyList()
}
fun MemberDescriptor.findCompatibleExpectedForActual(moduleFilter: ModuleFilter): List<MemberDescriptor> =
findExpectedForActual(this, moduleFilter)?.get(Compatible).orEmpty()
fun findActualForExpected( fun findActualForExpected(
expected: MemberDescriptor, expected: MemberDescriptor,
platformModule: ModuleDescriptor, platformModule: ModuleDescriptor,
moduleVisibilityFilter: ModuleFilter, moduleVisibilityFilter: ModuleFilter = allModulesProvidingActualsFor(expected.module),
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? { ): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
return when (expected) { return when (expected) {
is CallableMemberDescriptor -> { is CallableMemberDescriptor -> {
@@ -69,7 +56,7 @@ object ExpectedActualResolver {
fun findExpectedForActual( fun findExpectedForActual(
actual: MemberDescriptor, actual: MemberDescriptor,
moduleFilter: (ModuleDescriptor) -> Boolean moduleFilter: (ModuleDescriptor) -> Boolean = allModulesProvidingExpectsFor(actual.module)
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? { ): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
return when (actual) { return when (actual) {
is CallableMemberDescriptor -> { is CallableMemberDescriptor -> {
@@ -533,19 +520,39 @@ object ExpectedActualResolver {
} }
} }
fun DeclarationDescriptor.findExpects(): List<MemberDescriptor> { // FIXME(dsavvinov): review clients, as they won't work properly in HMPP projects
return ExpectedActualResolver.findExpectedForActual( @JvmOverloads
this as MemberDescriptor, ALL_MODULES fun MemberDescriptor.findCompatibleActualsForExpected(
)?.get(Compatible).orEmpty() platformModule: ModuleDescriptor, moduleFilter: ModuleFilter = allModulesProvidingActualsFor(module)
): List<MemberDescriptor> =
ExpectedActualResolver.findActualForExpected(this, platformModule, moduleFilter)?.get(Compatible).orEmpty()
@JvmOverloads
fun MemberDescriptor.findAnyActualsForExpected(
platformModule: ModuleDescriptor, moduleFilter: ModuleFilter = allModulesProvidingActualsFor(module)
): List<MemberDescriptor> {
val actualsGroupedByCompatibility = ExpectedActualResolver.findActualForExpected(this, platformModule, moduleFilter)
return actualsGroupedByCompatibility?.get(Compatible)
?: actualsGroupedByCompatibility?.values?.flatten()
?: emptyList()
} }
fun DeclarationDescriptor.findActuals(inModule: ModuleDescriptor = this.module): List<MemberDescriptor> { fun MemberDescriptor.findCompatibleExpectsForActual(
return ExpectedActualResolver.findActualForExpected( moduleFilter: ModuleFilter = allModulesProvidingExpectsFor(module)
(this as MemberDescriptor), inModule, ALL_MODULES ): List<MemberDescriptor> =
)?.get(Compatible).orEmpty() ExpectedActualResolver.findExpectedForActual(this, moduleFilter)?.get(Compatible).orEmpty()
fun DeclarationDescriptor.findExpects(): List<MemberDescriptor> {
if(this !is MemberDescriptor) return emptyList()
return this.findCompatibleExpectsForActual()
}
fun DeclarationDescriptor.findActuals(inModule: ModuleDescriptor): List<MemberDescriptor> {
if(this !is MemberDescriptor) return emptyList()
return this.findCompatibleActualsForExpected(inModule)
} }
// TODO: Klibs still need to better handle source in deserialized descriptors. // TODO: Klibs still need to better handle source in deserialized descriptors.
val DeclarationDescriptorWithSource.couldHaveASource: Boolean get() = val DeclarationDescriptorWithSource.couldHaveASource: Boolean
this.source.containingFile != SourceFile.NO_SOURCE_FILE || get() = this.source.containingFile != SourceFile.NO_SOURCE_FILE ||
this is DeserializedDescriptor this is DeserializedDescriptor
@@ -19,9 +19,7 @@ object OptionalAnnotationUtil {
assert(descriptor.isExpect) { "Not an expected class: $descriptor" } assert(descriptor.isExpect) { "Not an expected class: $descriptor" }
if (isOptionalAnnotationClass(descriptor)) { if (isOptionalAnnotationClass(descriptor)) {
with(ExpectedActualResolver) { return descriptor.findCompatibleActualsForExpected(descriptor.module).isEmpty()
return descriptor.findCompatibleActualForExpected(descriptor.module).isEmpty()
}
} }
return false return false
@@ -15,4 +15,12 @@ fun onlyFromThisModule(module: ModuleDescriptor): ModuleFilter = { it == module
val ALL_MODULES: ModuleFilter = { true } val ALL_MODULES: ModuleFilter = { true }
fun allModulesProvidingExpectsFor(platformModule: ModuleDescriptor): ModuleFilter = {
it == platformModule || it in platformModule.allExpectedByModules
}
fun allModulesProvidingActualsFor(commonModule: ModuleDescriptor): ModuleFilter = {
it == commonModule || commonModule in it.allExpectedByModules
}
fun <T : DeclarationDescriptor> Iterable<T>.applyFilter(filter: ModuleFilter): List<T> = filter { filter(it.module) } fun <T : DeclarationDescriptor> Iterable<T>.applyFilter(filter: ModuleFilter): List<T> = filter { filter(it.module) }