[FIR] Search for typealias in dependencies, if expect class was found first

^KT-65840 Fixed
This commit is contained in:
Dmitriy Novozhilov
2024-02-25 10:23:34 +02:00
committed by Space Team
parent c3c2f6f90a
commit eb85caedad
9 changed files with 89 additions and 1 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.caches.createCache
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.caches.getValue
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.isNewPlaceForBodyGeneration
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
@@ -322,6 +323,25 @@ abstract class AbstractFirDeserializedSymbolProvider(
}
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? {
return getClass(classId) ?: getTypeAlias(classId)
/**
* FIR has a contract that providers should return the first classifier with required classId they found.
*
* But on the other hand, there is a contract (from pre 1.0 times), that classes have more priority than typealiases,
* when search is performed in binary dependencies.
*
* And the second contract breaks the first in case, when there are two parts of a MPP library:
* - one is platform one and contains `actual typealias`
* - second is common one and contains `expect class`
*
* In this case, by the first contract, provider will return `expect class`, but FIR expects that `actual typealias` will be found
* So, to avoid this problem, we need to search for typealias in case, when `expect class` was found
*
* For details see KT-65840
*/
val clazz = getClass(classId)
if (clazz != null && !clazz.isExpect) {
return clazz
}
return getTypeAlias(classId) ?: clazz
}
}
@@ -220,6 +220,16 @@ class CustomK2Tests : KGPBaseTest() {
}
}
}
@GradleTest
@DisplayName("Native metadata compilation against other klib (KT-65840)")
fun nativeMetadataCompilationWithAgainstOtherKlib(gradleVersion: GradleVersion) {
project("k2-common-native-against-other-klib", gradleVersion) {
build(":app:compileNativeMainKotlinMetadata") {
assertTasksExecuted(":app:compileNativeMainKotlinMetadata")
}
}
}
}
@NativeGradlePluginTests
@@ -0,0 +1,7 @@
kotlin {
sourceSets {
commonMain.dependencies {
implementation(project(":lib"))
}
}
}
@@ -0,0 +1,37 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
group = "test"
version = "1.0"
plugins {
kotlin("multiplatform")
}
repositories {
mavenLocal()
mavenCentral()
}
subprojects {
apply {
plugin("kotlin-multiplatform")
}
kotlin {
applyDefaultHierarchyTemplate()
linuxX64()
macosX64()
}
repositories {
mavenLocal()
mavenCentral()
}
tasks.withType<KotlinCompilationTask<*>>().configureEach {
compilerOptions {
freeCompilerArgs.add("-Xrender-internal-diagnostic-names")
}
}
}
@@ -0,0 +1,7 @@
class Other {
fun foo() {}
}
actual typealias Some = Other
fun createSome(): Some = Other()