[FIR] Fix ambiguity of Throws and other std annotations importing

Including `SharedImmutable` and `ThreadLocal`

Simplify code, remove `DefaultImportPriority.KOTLIN_THROWS`

Introduce `FirNativeClassMapper`
This commit is contained in:
Ivan Kochurkin
2023-11-14 17:22:13 +01:00
committed by Space Team
parent adf4f823ae
commit 115d685d91
151 changed files with 656 additions and 931 deletions
+1
View File
@@ -7,6 +7,7 @@ dependencies {
api(project(":core:descriptors.jvm"))
api(project(":compiler:frontend.java"))
api(project(":compiler:fir:java"))
api(project(":compiler:fir:native"))
api(project(":compiler:fir:raw-fir:psi2fir"))
api(project(":compiler:fir:raw-fir:light-tree2fir"))
api(project(":compiler:fir:fir2ir"))
@@ -9,12 +9,15 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.SessionConfiguration
import org.jetbrains.kotlin.fir.backend.native.FirNativeClassMapper
import org.jetbrains.kotlin.fir.checkers.registerNativeCheckers
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSyntheticFunctionInterfaceProvider
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.session.FirSessionFactoryHelper.registerDefaultComponents
import org.jetbrains.kotlin.library.isNativeStdlib
import org.jetbrains.kotlin.library.metadata.impl.KlibResolvedModuleDescriptorsFactoryImpl.Companion.FORWARD_DECLARATIONS_MODULE_NAME
@@ -22,6 +25,7 @@ import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name
object FirNativeSessionFactory : FirAbstractSessionFactory() {
@OptIn(SessionConfiguration::class)
fun createLibrarySession(
mainModuleName: Name,
resolvedLibraries: List<KotlinResolvedLibrary>,
@@ -39,6 +43,7 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
extensionRegistrars,
registerExtraComponents = { session ->
session.registerDefaultComponents()
session.register(FirPlatformClassMapper::class, FirNativeClassMapper())
registerExtraComponents(session)
},
createKotlinScopeProvider = { FirKotlinScopeProvider() },
@@ -64,6 +69,7 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
})
}
@OptIn(SessionConfiguration::class)
fun createModuleBasedSession(
moduleData: FirModuleData,
sessionProvider: FirProjectSessionProvider,
@@ -83,6 +89,7 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
init,
registerExtraComponents = {
it.registerDefaultComponents()
it.register(FirPlatformClassMapper::class, FirNativeClassMapper())
registerExtraComponents(it)
},
registerExtraCheckers = { it.registerNativeCheckers() },
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmStandardClassIds
@NoMutableState
class FirJavaClassMapper(private val session: FirSession) : FirPlatformClassMapper() {
@@ -30,4 +31,8 @@ class FirJavaClassMapper(private val session: FirSession) : FirPlatformClassMapp
if (classId == null) return null
return JavaToKotlinClassMap.mapJavaToKotlin(classId.asSingleFqName())
}
override val classTypealiasesThatDontCauseAmbiguity: Map<ClassId, ClassId> = mapOf(
JvmStandardClassIds.Annotations.Throws to JvmStandardClassIds.Annotations.ThrowsAlias,
)
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.backend.native
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.NativeRuntimeNames
class FirNativeClassMapper : FirPlatformClassMapper() {
override fun getCorrespondingPlatformClass(declaration: FirClassLikeDeclaration): FirRegularClass? {
return null
}
override fun getCorrespondingPlatformClass(classId: ClassId?): ClassId? {
return null
}
override fun getCorrespondingKotlinClass(classId: ClassId?): ClassId? {
return null
}
override val classTypealiasesThatDontCauseAmbiguity: Map<ClassId, ClassId> = mapOf(
NativeRuntimeNames.Annotations.Throws to NativeRuntimeNames.Annotations.ThrowsAlias,
NativeRuntimeNames.Annotations.SharedImmutable to NativeRuntimeNames.Annotations.SharedImmutableAlias,
NativeRuntimeNames.Annotations.ThreadLocal to NativeRuntimeNames.Annotations.ThreadLocalAlias
)
}
@@ -26,6 +26,8 @@ abstract class FirPlatformClassMapper : FirSessionComponent {
override fun getCorrespondingKotlinClass(classId: ClassId?): ClassId? {
return null
}
override val classTypealiasesThatDontCauseAmbiguity: Map<ClassId, ClassId> = emptyMap()
}
abstract fun getCorrespondingPlatformClass(declaration: FirClassLikeDeclaration): FirRegularClass?
@@ -33,6 +35,12 @@ abstract class FirPlatformClassMapper : FirSessionComponent {
abstract fun getCorrespondingPlatformClass(classId: ClassId?): ClassId?
abstract fun getCorrespondingKotlinClass(classId: ClassId?): ClassId?
// Compiler should not report ambiguity for certain platform classes and their type aliases
// For instance, there is no ambiguity between `kotlin.Throws` and `kotlin.jvm.Throws`
// To achieve this goal, `FirTypeResolver` uses this map and tries to find candidates with identifiers from the map's keys
// And remove corresponding type aliases (value of map) if they are presented in the candidate set
abstract val classTypealiasesThatDontCauseAmbiguity: Map<ClassId, ClassId>
}
val FirSession.platformClassMapper: FirPlatformClassMapper by FirSession.sessionComponentAccessor()
@@ -25,14 +25,6 @@ enum class DefaultImportPriority {
languageVersionSettings: LanguageVersionSettings
): List<ImportPath>? =
platformDependentAnalyzerServices?.defaultLowPriorityImports
},
KOTLIN_THROWS {
override fun getAllDefaultImports(
platformDependentAnalyzerServices: PlatformDependentAnalyzerServices?,
languageVersionSettings: LanguageVersionSettings
): List<ImportPath> {
return listOf(ImportPath.fromString("kotlin.Throws"))
}
};
abstract fun getAllDefaultImports(
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.ResolutionDiagnostic
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
import org.jetbrains.kotlin.fir.scopes.platformClassMapper
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
@@ -134,6 +135,8 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
}
}
filterOutAmbiguousTypealiases(candidates)
val candidateCount = candidates.size
return when {
candidateCount == 1 -> {
@@ -150,6 +153,24 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
}
}
private fun filterOutAmbiguousTypealiases(candidates: MutableSet<TypeCandidate>) {
if (candidates.size <= 1) return
val aliasesToRemove = mutableSetOf<ClassId>()
val classTypealiasesThatDontCauseAmbiguity = session.platformClassMapper.classTypealiasesThatDontCauseAmbiguity
for (candidate in candidates) {
val symbol = candidate.symbol
if (symbol is FirClassLikeSymbol<*>) {
classTypealiasesThatDontCauseAmbiguity[symbol.classId]?.let { aliasesToRemove.add(it) }
}
}
if (aliasesToRemove.isNotEmpty()) {
candidates.removeAll {
(it.symbol as? FirClassLikeSymbol)?.classId?.let { classId -> aliasesToRemove.contains(classId) } == true
}
}
}
sealed class TypeResolutionResult {
class Ambiguity(val typeCandidates: List<TypeCandidate>) : TypeResolutionResult()
object Unresolved : TypeResolutionResult()
@@ -70,10 +70,6 @@ internal fun computeImportingScopes(
FirSingleLevelDefaultStarImportingScope(session, scopeSession, DefaultImportPriority.LOW, excludedImportNames)
},
)
this += scopeSession.getOrBuild(DefaultSimpleImportKey(DefaultImportPriority.KOTLIN_THROWS, excludedImportNames), DEFAULT_SIMPLE_IMPORT) {
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.KOTLIN_THROWS, excludedImportNames)
}
}
this += FirExplicitStarImportingScope(file.imports, session, scopeSession, excludedImportNames)
@@ -0,0 +1,11 @@
import kotlin.*
import kotlin.jvm.*
import kotlin.native.concurrent.*
import kotlin.native.*
@<!DEPRECATION!>SharedImmutable<!>
@ThreadLocal
val x = 42
@Throws(Exception::class)
fun test() {}
@@ -0,0 +1,11 @@
import kotlin.*
import kotlin.jvm.*
import kotlin.native.concurrent.*
import kotlin.native.*
@<!DEPRECATION, TYPEALIAS_EXPANSION_DEPRECATION!>SharedImmutable<!>
@<!DEPRECATION!>ThreadLocal<!>
val x = 42
@Throws(Exception::class)
fun test() {}
@@ -72,7 +72,7 @@ package abc4
import kotlin.<!CONFLICTING_IMPORT!>Throws<!>
import <!DEPRECATION!>kotlin.native.<!CONFLICTING_IMPORT!>Throws<!><!>
@<!OVERLOAD_RESOLUTION_AMBIGUITY!>Throws<!>(Throwable::class)
@Throws(Throwable::class)
fun foo1() {}
@kotlin.Throws(Throwable::class)
@@ -81,7 +81,7 @@ fun foo2() {}
@<!DEPRECATION!>kotlin.native.Throws<!>(Throwable::class)
fun foo3() {}
fun foo5(x: <!OVERLOAD_RESOLUTION_AMBIGUITY!>Throws<!>) {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: <!DEPRECATION!>kotlin.native.Throws<!>) {}
@@ -127,7 +127,7 @@ package abc7
import kotlin.*
import kotlin.native.*
@<!OVERLOAD_RESOLUTION_AMBIGUITY!>Throws<!>(Throwable::class)
@Throws(Throwable::class)
fun foo1() {}
@kotlin.Throws(Throwable::class)
@@ -136,7 +136,7 @@ fun foo2() {}
@<!DEPRECATION!>kotlin.native.Throws<!>(Throwable::class)
fun foo3() {}
fun foo5(x: <!OVERLOAD_RESOLUTION_AMBIGUITY!>Throws<!>) {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: <!DEPRECATION!>kotlin.native.Throws<!>) {}
@@ -1,164 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: main1.kt
package abc1
@Throws(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
// FILE: main2.kt
package abc2
import kotlin.jvm.Throws
@Throws(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
// FILE: main3.kt
package abc3
import kotlin.Throws
@Throws(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
// FILE: main4.kt
package abc4
import kotlin.<!CONFLICTING_IMPORT!>Throws<!>
import kotlin.jvm.<!CONFLICTING_IMPORT!>Throws<!>
@<!OVERLOAD_RESOLUTION_AMBIGUITY!>Throws<!>(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: <!OVERLOAD_RESOLUTION_AMBIGUITY!>Throws<!>) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
// FILE: main5.kt
package abc5
import kotlin.jvm.*
@Throws(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
// FILE: main6.kt
package abc6
import kotlin.*
@Throws(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
// FILE: main7.kt
package abc7
import kotlin.*
import kotlin.jvm.*
@<!OVERLOAD_RESOLUTION_AMBIGUITY!>Throws<!>(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: <!OVERLOAD_RESOLUTION_AMBIGUITY!>Throws<!>) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
// FILE: main8.kt
package abc8
import kotlin.*
import kotlin.jvm.Throws
@Throws(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
// FILE: main9.kt
package abc9
import kotlin.jvm.*
import kotlin.Throws
@Throws(Exception::class)
fun foo1() {}
@kotlin.Throws(Exception::class)
fun foo2() {}
@kotlin.jvm.Throws(Exception::class)
fun foo3() {}
fun foo5(x: Throws) {}
fun foo6(x: kotlin.Throws) {}
fun foo7(x: kotlin.jvm.Throws) {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: main1.kt
package abc1