[FIR] Sort HMPP dependencies topologically for symbol providers

This fixes an issue where an actual class from an intermediate module
has more supertypes than its expect declaration which leads to a
false-positive resolution error because a type reference resolves to the
expect class. The fix is to sort the dependencies topologically from
"most actual" to "most expect" when creating the list of symbol
providers.

#KT-57369 Fixed
This commit is contained in:
Kirill Rakhman
2023-03-22 12:10:48 +01:00
committed by Space Team
parent 6fe0849402
commit 60b227c519
15 changed files with 174 additions and 33 deletions
@@ -550,6 +550,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/hmpp"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("intermediateActualHasAdditionalSupertypes.kt")
public void testIntermediateActualHasAdditionalSupertypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/intermediateActualHasAdditionalSupertypes.kt");
}
@Test
@TestMetadata("kt-55570.kt")
public void testKt_55570() throws Exception {
@@ -550,6 +550,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/hmpp"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("intermediateActualHasAdditionalSupertypes.kt")
public void testIntermediateActualHasAdditionalSupertypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/intermediateActualHasAdditionalSupertypes.kt");
}
@Test
@TestMetadata("kt-55570.kt")
public void testKt_55570() throws Exception {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.session
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.topologicalSort
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
@@ -139,7 +140,13 @@ abstract class FirAbstractSessionFactory {
private fun FirSession.computeDependencyProviderList(moduleData: FirModuleData): List<FirSymbolProvider> {
val visited = mutableSetOf<FirSymbolProvider>()
return (moduleData.dependencies + moduleData.friendDependencies + moduleData.dependsOnDependencies)
// dependsOnDependencies can actualize declarations from their dependencies. Because actual declarations can be more specific
// (e.g. have additional supertypes), the modules must be ordered from most specific (i.e. actual) to most generic (i.e. expect)
// to prevent false positive resolution errors (see KT-57369 for an example).
val dependsOnDependencies = topologicalSort(moduleData.dependsOnDependencies) { it.dependsOnDependencies }
return (moduleData.dependencies + moduleData.friendDependencies + dependsOnDependencies)
.mapNotNull { sessionProvider?.getSession(it) }
.map { it.symbolProvider }
.flatMap { it.flatten(visited, collectSourceProviders = it.session.kind == FirSession.Kind.Source) }