attempt to use pfps; not quite OK, as it seems way to low-level
diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 0dabf9b..4249ed3 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml
@@ -32,5 +32,6 @@ </component> <component name="VcsDirectoryMappings"> <mapping directory="" vcs="Git" /> + <mapping directory="$PROJECT_DIR$/kotlin-ultimate" vcs="Git" /> </component> </project> \ No newline at end of file
diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibilityChecker.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibilityChecker.kt index c16592c..30d92cd 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibilityChecker.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibilityChecker.kt
@@ -22,7 +22,11 @@ import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.keysToMap -internal class ExpectedActualCompatibilityChecker(private val platformModule: ModuleDescriptor) { +internal class ExpectedActualCompatibilityChecker( + // NB: It is *required* that this package fragment provider has scope of *platform* declaration *with* all dependencies, + // as it will be used for "actual typealias" resolution + private val packageFragmentProviderWithPlatformDependencies: PackageFragmentProvider +) { internal fun areCompatibleClassifiers(a: ClassDescriptor, other: ClassifierDescriptor): Compatibility { // Can't check FQ names here because nested expected class may be implemented via actual typealias's expansion with the other FQ name assert(a.name == other.name) { "This function should be invoked only for declarations with the same name: $a, $other" } @@ -173,7 +177,7 @@ return expected is ClassifierDescriptorWithTypeParameters && expected.isExpect && actual is ClassifierDescriptorWithTypeParameters && - expected.findClassifiersFromModule(platformModule, includeDependencies = true).any { classifier -> + expected.findClassifiersFromModule(packageFragmentProviderWithPlatformDependencies).any { classifier -> // Note that it's fine to only check that this "actual typealias" expands to the expected class, without checking // whether the type arguments in the expansion are in the correct order or have the correct variance, because we only // allow simple cases like "actual typealias Foo<A, B> = FooImpl<A, B>", see DeclarationsChecker#checkActualTypeAlias
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 56eee17..75e0c95 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt
@@ -6,6 +6,7 @@ package org.jetbrains.kotlin.resolve.multiplatform import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualCompatibilityChecker.Substitutor import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Compatible @@ -58,10 +59,14 @@ expected: MemberDescriptor, platformModule: ModuleDescriptor ): Map<Compatibility, List<MemberDescriptor>>? { - val compatibilityChecker = ExpectedActualCompatibilityChecker(platformModule) + val packageFragmentProviderWithoutDependencies = + (platformModule as ModuleDescriptorImpl).packageFragmentProviderForModuleContentWithoutDependencies + val packageFragmentProviderWithDependencies = platformModule.packageFragmentProvider + val compatibilityChecker = ExpectedActualCompatibilityChecker(packageFragmentProviderWithDependencies) + return when (expected) { is CallableMemberDescriptor -> { - expected.findNamesakesFromModule(platformModule).filter { actual -> + expected.findNamesakesFromModule(packageFragmentProviderWithoutDependencies).filter { actual -> expected != actual && !actual.isExpect && // TODO: use some other way to determine that the declaration is from Kotlin. // This way behavior differs between fast and PSI-based Java class reading mode @@ -72,7 +77,7 @@ } } is ClassDescriptor -> { - expected.findClassifiersFromModule(platformModule).filter { actual -> + expected.findClassifiersFromModule(packageFragmentProviderWithoutDependencies).filter { actual -> expected != actual && !actual.isExpect && actual.couldHaveASource }.groupBy { actual -> @@ -87,7 +92,10 @@ actual: MemberDescriptor, commonModule: ModuleDescriptor ): Map<Compatibility, List<MemberDescriptor>>? { - val compatibilityChecker = ExpectedActualCompatibilityChecker(actual.module) + val commonPackageFragmentProvider = + (commonModule as ModuleDescriptorImpl).packageFragmentProviderForModuleContentWithoutDependencies + val packageFragmentProviderWithPlatformDependencies = (actual.module as ModuleDescriptorImpl).packageFragmentProvider + val compatibilityChecker = ExpectedActualCompatibilityChecker(packageFragmentProviderWithPlatformDependencies) return when (actual) { is CallableMemberDescriptor -> { @@ -99,7 +107,7 @@ findExpectedForActual(container, commonModule)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor expectedClass?.getMembers(actual.name)?.filterIsInstance<CallableMemberDescriptor>().orEmpty() } - is PackageFragmentDescriptor -> actual.findNamesakesFromModule(commonModule) + is PackageFragmentDescriptor -> actual.findNamesakesFromModule(commonPackageFragmentProvider) else -> return null // do not report anything for incorrect code, e.g. 'actual' local function } @@ -117,7 +125,7 @@ } } is ClassifierDescriptorWithTypeParameters -> { - actual.findClassifiersFromModule(commonModule).filter { declaration -> + actual.findClassifiersFromModule(commonPackageFragmentProvider).filter { declaration -> actual != declaration && declaration is ClassDescriptor && declaration.isExpect }.groupBy { expected ->
diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/utils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/utils.kt index 3ffd393..19d07a1 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/utils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/utils.kt
@@ -6,7 +6,6 @@ package org.jetbrains.kotlin.resolve.multiplatform import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -27,14 +26,14 @@ this is DeserializedClassDescriptor internal fun CallableMemberDescriptor.findNamesakesFromModule( - module: ModuleDescriptor + packageFragmentProvider: PackageFragmentProvider ): Collection<CallableMemberDescriptor> { val scopes = when (val containingDeclaration = containingDeclaration) { is PackageFragmentDescriptor -> { - listOf(module.getPackageMemberScopeWithoutDependencies(containingDeclaration.fqName)) + listOf(packageFragmentProvider.getPackageMemberScope(containingDeclaration.fqName)) } is ClassDescriptor -> { - val classes = containingDeclaration.findClassifiersFromModule(module) + val classes = containingDeclaration.findClassifiersFromModule(packageFragmentProvider) .mapNotNull { if (it is TypeAliasDescriptor) it.classDescriptor else it } .filterIsInstance<ClassDescriptor>() if (this is ConstructorDescriptor) return classes.flatMap { it.constructors } @@ -62,8 +61,7 @@ } internal fun ClassifierDescriptorWithTypeParameters.findClassifiersFromModule( - module: ModuleDescriptor, - includeDependencies: Boolean = false + packageFragmentProvider: PackageFragmentProvider ): Collection<ClassifierDescriptorWithTypeParameters> { val classId = classId ?: return emptyList() @@ -73,10 +71,7 @@ val segments = classId.relativeClassName.pathSegments() - val scope = if (includeDependencies) - module.getPackage(classId.packageFqName).memberScope - else - module.getPackageMemberScopeWithoutDependencies(classId.packageFqName) + val scope = packageFragmentProvider.getPackageMemberScope(classId.packageFqName) var classifiers = scope.getAllClassifiers(segments.first()) @@ -101,10 +96,7 @@ } -internal fun ModuleDescriptor.getPackageMemberScopeWithoutDependencies(fqName: FqName): MemberScope { - require(this is ModuleDescriptorImpl) { "Unexpected subtype of ModuleDescriptor: ${this::class}" } - - val memberScopes = packageFragmentProviderForModuleContentWithoutDependencies.getPackageFragments(fqName) - .map { it.getMemberScope() } - return ChainedMemberScope("Scope of package $fqName in module $this without dependencies", memberScopes) +internal fun PackageFragmentProvider.getPackageMemberScope(fqName: FqName): MemberScope { + val memberScopes = getPackageFragments(fqName).map { it.getMemberScope() } + return ChainedMemberScope("Scope of package $fqName from PackageFragmentProvider $this", memberScopes) }