[FIR2IR] Provide correct module data to FirModuleDescriptor

Properly implement friend modules visibility check

^KT-61384 Fixed
^KT-62475 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-10-11 12:52:04 +03:00
committed by Space Team
parent e3bab4a7da
commit c25cde8871
11 changed files with 73 additions and 48 deletions
@@ -554,7 +554,7 @@ class Fir2IrConverter(
typeContextProvider: (IrBuiltIns) -> IrTypeSystemContext
): Fir2IrResult {
session.lazyDeclarationResolver.disableLazyResolveContractChecks()
val moduleDescriptor = FirModuleDescriptor(session, kotlinBuiltIns)
val moduleDescriptor = FirModuleDescriptor.createSourceModuleDescriptor(session, kotlinBuiltIns)
val components = Fir2IrComponentsStorage(
session, scopeSession, irFactory, fir2IrExtensions, fir2IrConfiguration, visibilityConverter,
{ irBuiltins ->
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
import org.jetbrains.kotlin.name.*
@@ -48,19 +47,18 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.threadLocal
import java.util.concurrent.ConcurrentHashMap
import org.jetbrains.kotlin.fir.java.hasJvmFieldAnnotation
@OptIn(LeakedDeclarationCaches::class)
class Fir2IrDeclarationStorage(
private val components: Fir2IrComponents,
private val moduleDescriptor: FirModuleDescriptor,
private val sourceModuleDescriptor: FirModuleDescriptor,
commonMemberStorage: Fir2IrCommonMemberStorage
) : Fir2IrComponents by components {
private val fragmentCache: ConcurrentHashMap<FqName, ExternalPackageFragments> = ConcurrentHashMap()
private class ExternalPackageFragments(
val fragmentForDependencies: IrExternalPackageFragment,
val fragmentsForDependencies: ConcurrentHashMap<FirModuleData, IrExternalPackageFragment>,
val fragmentForPrecompiledBinaries: IrExternalPackageFragment
)
@@ -156,32 +154,43 @@ class Fir2IrDeclarationStorage(
fun getIrExternalPackageFragment(
fqName: FqName,
moduleData: FirModuleData,
firOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library
): IrExternalPackageFragment {
val fragments = fragmentCache.getOrPut(fqName) {
val fragmentForDependencies = callablesGenerator.createExternalPackageFragment(
fqName, FirModuleDescriptor(session, moduleDescriptor.builtIns)
)
val fragmentForPrecompiledBinaries = callablesGenerator.createExternalPackageFragment(fqName, moduleDescriptor)
ExternalPackageFragments(fragmentForDependencies, fragmentForPrecompiledBinaries)
val fragmentForPrecompiledBinaries = callablesGenerator.createExternalPackageFragment(fqName, sourceModuleDescriptor)
ExternalPackageFragments(ConcurrentHashMap(), fragmentForPrecompiledBinaries)
}
// Make sure that external package fragments have a different module descriptor. The module descriptors are compared
// to determine if objects need regeneration because they are from different modules.
// But keep original module descriptor for the fragments coming from parts compiled on the previous incremental step
return when (firOrigin) {
FirDeclarationOrigin.Precompiled -> fragments.fragmentForPrecompiledBinaries
else -> fragments.fragmentForDependencies
else -> fragments.fragmentsForDependencies.getOrPut(moduleData) {
val moduleDescriptor = FirModuleDescriptor.createDependencyModuleDescriptor(
moduleData,
sourceModuleDescriptor.builtIns
)
callablesGenerator.createExternalPackageFragment(fqName, moduleDescriptor)
}
}
}
private fun getIrExternalOrBuiltInsPackageFragment(fqName: FqName, firOrigin: FirDeclarationOrigin): IrExternalPackageFragment {
private fun getIrExternalOrBuiltInsPackageFragment(
fqName: FqName,
moduleData: FirModuleData,
firOrigin: FirDeclarationOrigin,
): IrExternalPackageFragment {
val isBuiltIn = fqName in BUILT_INS_PACKAGE_FQ_NAMES
return if (isBuiltIn) getIrBuiltInsPackageFragment(fqName) else getIrExternalPackageFragment(fqName, firOrigin)
return when(isBuiltIn) {
true -> getIrBuiltInsPackageFragment(fqName)
false -> getIrExternalPackageFragment(fqName, moduleData, firOrigin)
}
}
private fun getIrBuiltInsPackageFragment(fqName: FqName): IrExternalPackageFragment {
return builtInsFragmentCache.getOrPut(fqName) {
callablesGenerator.createExternalPackageFragment(FirBuiltInsPackageFragment(fqName, moduleDescriptor))
callablesGenerator.createExternalPackageFragment(FirBuiltInsPackageFragment(fqName, sourceModuleDescriptor))
}
}
@@ -1164,12 +1173,12 @@ class Fir2IrDeclarationStorage(
val parentPackage = when (firBasedSymbol) {
is FirCallableSymbol<*> -> {
getIrExternalPackageFragment(packageFqName, firOrigin)
getIrExternalPackageFragment(packageFqName, firBasedSymbol.moduleData, firOrigin)
}
else -> {
// TODO: All classes from BUILT_INS_PACKAGE_FQ_NAMES are considered built-ins now,
// which is not exact and can lead to some problems
getIrExternalOrBuiltInsPackageFragment(packageFqName, firOrigin)
getIrExternalOrBuiltInsPackageFragment(packageFqName, firBasedSymbol.moduleData, firOrigin)
}
}
@@ -66,13 +66,11 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
val nameSegments = signature.nameSegments
val topName = Name.identifier(nameSegments[0])
val packageFragment = declarationStorage.getIrExternalPackageFragment(packageFqName)
val firCandidates: List<FirDeclaration>
val parent: IrDeclarationParent
val parentClass: IrClass?
if (nameSegments.size == 1 && kind != SymbolKind.CLASS_SYMBOL) {
firCandidates = symbolProvider.getTopLevelCallableSymbols(packageFqName, topName).map { it.fir }
parent = packageFragment // TODO: need to insert file facade class on JVM
parentClass = null // TODO: need to insert file facade class on JVM
} else {
val topLevelClass = symbolProvider.getClassLikeSymbolByClassId(ClassId(packageFqName, topName))?.fir as? FirRegularClass
?: return null
@@ -95,28 +93,28 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
when (kind) {
SymbolKind.CLASS_SYMBOL -> {
firCandidates = listOf(firClass)
parent = firParentClass?.let { findIrClass(it) } ?: packageFragment
parentClass = firParentClass?.let { findIrClass(it) }
}
SymbolKind.ENUM_ENTRY_SYMBOL -> {
val lastName = Name.guessByFirstCharacter(nameSegments.last())
val firCandidate = firClass.declarations.singleOrNull { (it as? FirEnumEntry)?.name == lastName }
firCandidates = firCandidate?.let { listOf(it) } ?: return null
parent = findIrClass(firClass)
parentClass = findIrClass(firClass)
}
SymbolKind.CONSTRUCTOR_SYMBOL -> {
val constructors = mutableListOf<FirConstructor>()
scope.processDeclaredConstructors { constructors.add(it.fir) }
firCandidates = constructors
parent = findIrClass(firClass)
parentClass = findIrClass(firClass)
}
SymbolKind.FUNCTION_SYMBOL -> {
parent = findIrClass(firClass)
parentClass = findIrClass(firClass)
val lastName = Name.guessByFirstCharacter(nameSegments.last())
val functions = mutableListOf<FirSimpleFunction>()
scope.processFunctionsByName(lastName) { functionSymbol ->
val dispatchReceiverClassId = (functionSymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
val function = if (dispatchReceiverClassId != null && dispatchReceiverClassId != classId) {
fakeOverrideGenerator.createFirFunctionFakeOverride(firClass, parent, functionSymbol, scope)!!.first
fakeOverrideGenerator.createFirFunctionFakeOverride(firClass, parentClass, functionSymbol, scope)!!.first
} else functionSymbol.fir
functions.add(function)
}
@@ -126,21 +124,21 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
firCandidates = functions
}
SymbolKind.PROPERTY_SYMBOL -> {
parent = findIrClass(firClass)
parentClass = findIrClass(firClass)
val lastName = Name.guessByFirstCharacter(nameSegments.last())
val properties = mutableListOf<FirVariable>()
scope.processPropertiesByName(lastName) { propertySymbol ->
propertySymbol as FirPropertySymbol
val dispatchReceiverClassId = (propertySymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
val property = if (dispatchReceiverClassId != null && dispatchReceiverClassId != classId) {
fakeOverrideGenerator.createFirPropertyFakeOverride(firClass, parent, propertySymbol, scope)!!.first
fakeOverrideGenerator.createFirPropertyFakeOverride(firClass, parentClass, propertySymbol, scope)!!.first
} else propertySymbol.fir
properties.add(property)
}
firCandidates = properties
}
SymbolKind.FIELD_SYMBOL -> {
parent = findIrClass(firClass)
parentClass = findIrClass(firClass)
val lastName = Name.guessByFirstCharacter(nameSegments.last())
val fields = mutableListOf<FirVariable>()
scope.processPropertiesByName(lastName) { propertySymbol ->
@@ -154,13 +152,13 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
else -> {
val lastName = nameSegments.last()
firCandidates = firClass.declarations.filter { it is FirCallableDeclaration && it.symbol.name.asString() == lastName }
parent = findIrClass(firClass)
parentClass = findIrClass(firClass)
}
}
}
val firDeclaration = findDeclarationByHash(firCandidates, signature.id)
?: return null
val firDeclaration = findDeclarationByHash(firCandidates, signature.id) ?: return null
val parent = parentClass ?: declarationStorage.getIrExternalPackageFragment(packageFqName, firDeclaration.moduleData)
return when (kind) {
SymbolKind.CLASS_SYMBOL -> {
@@ -699,7 +699,7 @@ class IrBuiltInsOverFir(
private fun findIrParent(firSymbol: FirCallableSymbol<*>): IrDeclarationParent? {
return when (val containingClassLookupTag = firSymbol.containingClassLookupTag()) {
null -> components.declarationStorage.getIrExternalPackageFragment(firSymbol.callableId.packageName)
null -> components.declarationStorage.getIrExternalPackageFragment(firSymbol.callableId.packageName, firSymbol.moduleData)
else -> components.classifierStorage.findIrClass(containingClassLookupTag)
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
@@ -468,7 +469,9 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
val parentId = classId.outerClassId
val parentClass = parentId?.let { createIrClassForNotFoundClass(it.toLookupTag()) }
val irParent = parentClass ?: declarationStorage.getIrExternalPackageFragment(classId.packageFqName)
val irParent = parentClass ?: declarationStorage.getIrExternalPackageFragment(
classId.packageFqName, session.moduleData.dependencies.first()
)
return symbolTable.declareClassIfNotExists(signature, { IrClassPublicSymbolImpl(signature) }) {
irFactory.createClass(
@@ -5,46 +5,66 @@
package org.jetbrains.kotlin.fir.descriptors
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
class FirModuleDescriptor(
class FirModuleDescriptor private constructor(
val session: FirSession,
val moduleData: FirModuleData,
override val builtIns: KotlinBuiltIns
) : ModuleDescriptor {
companion object {
fun createSourceModuleDescriptor(session: FirSession, builtIns: KotlinBuiltIns): FirModuleDescriptor {
require(session.kind == FirSession.Kind.Source)
return FirModuleDescriptor(session, session.moduleData, builtIns)
}
fun createDependencyModuleDescriptor(moduleData: FirModuleData, builtIns: KotlinBuiltIns): FirModuleDescriptor {
// We may create dependency module descriptor for java sources, which have source session and source module data
return FirModuleDescriptor(moduleData.session, moduleData, builtIns)
}
}
override fun shouldSeeInternalsOf(targetModule: ModuleDescriptor): Boolean {
return false
if (targetModule !is FirModuleDescriptor) return false
return when (targetModule.moduleData) {
this.moduleData,
in moduleData.friendDependencies,
in moduleData.dependsOnDependencies -> true
else -> false
}
}
override val platform: TargetPlatform
get() = session.moduleData.platform
get() = moduleData.platform
override fun getPackage(fqName: FqName): PackageViewDescriptor {
val symbolProvider = session.symbolProvider
if (symbolProvider.getPackage(fqName) != null) {
return FirPackageViewDescriptor(fqName, this)
}
TODO("Missing package reporting")
error("Module $moduleData doesn't contain package $fqName")
}
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
TODO("not implemented")
shouldNotBeCalled()
}
override var allDependencyModules: List<ModuleDescriptor> = emptyList()
override val expectedByModules: List<ModuleDescriptor>
get() = TODO("not implemented")
get() = shouldNotBeCalled()
override val allExpectedByModules: Set<ModuleDescriptor>
get() = TODO("not implemented")
get() = shouldNotBeCalled()
override fun <T> getCapability(capability: ModuleCapability<T>): T? {
return null
@@ -62,14 +82,14 @@ class FirModuleDescriptor(
}
override fun getName(): Name {
return session.moduleData.name
return moduleData.name
}
override val stableName: Name
get() = name
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?) {
TODO("not implemented")
shouldNotBeCalled()
}
override val annotations: Annotations
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: WASM
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-61384
// WITH_STDLIB
// MODULE: lib1
@@ -1,6 +1,5 @@
// IGNORE_BACKEND: WASM
// WITH_STDLIB
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-61384
// MODULE: lib1
@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-61384
// WITH_STDLIB
// MODULE: lib
@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-61384
// WITH_STDLIB
// MODULE: lib
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: WASM
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-61384
// MODULE: lib
// FILE: l.kt