[K2/N] KT-56030: Support Objective-C overloading by param names only

Merge-request: KT-MR-8901
Merged-by: Vladimir Sukharev <Vladimir.Sukharev@jetbrains.com>
This commit is contained in:
Vladimir Sukharev
2023-03-30 09:37:57 +00:00
committed by Space Team
parent c957a0b43b
commit b9633375b4
27 changed files with 852 additions and 309 deletions
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.prepareJsSessions
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
@@ -28,6 +27,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.Fir2IrVisibilityConverter
import org.jetbrains.kotlin.fir.backend.extractFirDeclarations
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
@@ -133,6 +133,7 @@ fun transformFirToIr(
linkViaSignatures = false,
signatureComposerCreator = null,
irMangler = JsManglerIr,
firManglerCreator = { FirJvmKotlinMangler() },
visibilityConverter = Fir2IrVisibilityConverter.Default,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
diagnosticReporter = diagnosticsReporter,
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.GroupedKtSources
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirModuleDataImpl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
@@ -160,6 +157,7 @@ fun <F> prepareNativeSessions(
extensionRegistrars: List<FirExtensionRegistrar>,
isCommonSource: (F) -> Boolean,
fileBelongsToModule: (F, String) -> Boolean,
registerExtraComponents: ((FirSession) -> Unit) = {},
): List<SessionWithSources<F>> {
return prepareSessions(
files, configuration, rootModuleName, NativePlatforms.unspecifiedNativePlatform, NativePlatformAnalyzerServices,
@@ -171,7 +169,7 @@ fun <F> prepareNativeSessions(
libraryList.moduleDataProvider,
extensionRegistrars,
configuration.languageVersionSettings,
registerExtraComponents = {},
registerExtraComponents,
)
}
) { _, moduleData, sessionProvider, sessionConfigurator ->
@@ -181,6 +179,7 @@ fun <F> prepareNativeSessions(
extensionRegistrars,
configuration.languageVersionSettings,
sessionConfigurator,
registerExtraComponents,
)
}
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.signaturer.FirMangler
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -55,6 +56,7 @@ fun FirResult.convertToIrAndActualizeForJvm(
linkViaSignatures = linkViaSignatures,
signatureComposerCreator = { JvmIdSignatureDescriptor(JvmDescriptorMangler(null)) },
irMangler = JvmIrMangler,
firManglerCreator = { FirJvmKotlinMangler() },
visibilityConverter = FirJvmVisibilityConverter,
diagnosticReporter = diagnosticReporter,
languageVersionSettings = languageVersionSettings,
@@ -67,6 +69,7 @@ fun FirResult.convertToIrAndActualize(
linkViaSignatures: Boolean,
signatureComposerCreator: (() -> IdSignatureComposer)?,
irMangler: KotlinMangler.IrMangler,
firManglerCreator: () -> FirMangler,
visibilityConverter: Fir2IrVisibilityConverter,
kotlinBuiltIns: KotlinBuiltIns,
diagnosticReporter: DiagnosticReporter,
@@ -79,7 +82,7 @@ fun FirResult.convertToIrAndActualize(
val commonMemberStorage = Fir2IrCommonMemberStorage(
generateSignatures = linkViaSignatures,
signatureComposerCreator = signatureComposerCreator,
manglerCreator = { FirJvmKotlinMangler() } // TODO: replace with potentially simpler version for other backends.
manglerCreator = firManglerCreator
)
when (outputs.size) {
@@ -94,7 +97,9 @@ fun FirResult.convertToIrAndActualize(
irMangler,
visibilityConverter,
kotlinBuiltIns,
)
).also { result ->
fir2IrResultPostCompute(result)
}
actualizationResult = null
}
else -> {
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.impl.FirTypeResolverImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirDummyCompilerLazyDeclarationResolver
import org.jetbrains.kotlin.fir.resolve.transformers.PlatformSupertypeUpdater
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
import org.jetbrains.kotlin.fir.scopes.FirOverrideService
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules
@@ -70,6 +71,8 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
register(FirSamConstructorStorage::class, FirSamConstructorStorage(this))
register(FirOverrideService::class, FirOverrideService(this))
register(FirDynamicMembersStorage::class, FirDynamicMembersStorage(this))
register(FirEnumEntriesSupport::class, FirEnumEntriesSupport(this))
register(FirOverrideChecker::class, FirStandardOverrideChecker(this))
}
@OptIn(SessionConfiguration::class)
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirExtensionSyntheticFunctionInterfaceProvider
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.scopes.impl.FirEnumEntriesSupport
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.Name
@@ -98,6 +97,5 @@ object FirJsSessionFactory : FirAbstractSessionFactory() {
register(ConeCallConflictResolverFactory::class, JsCallConflictResolverFactory)
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
register(FirOverridesBackwardCompatibilityHelper::class, FirOverridesBackwardCompatibilityHelper.Default())
register(FirEnumEntriesSupport::class, FirEnumEntriesSupport(this))
}
}
@@ -37,7 +37,9 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
moduleDataProvider,
languageVersionSettings,
extensionRegistrars,
registerExtraComponents,
registerExtraComponents = { session ->
registerExtraComponents(session)
},
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _, _ -> declaredMemberScope } },
createProviders = { session, builtinsModuleData, kotlinScopeProvider ->
val forwardDeclarationsModuleData = BinaryModuleData.createDependencyModuleData(
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.scopes.impl.FirEnumEntriesSupport
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
@@ -128,6 +127,5 @@ object FirSessionFactoryHelper {
register(ConeCallConflictResolverFactory::class, DefaultCallConflictResolverFactory)
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
register(FirOverridesBackwardCompatibilityHelper::class, FirOverridesBackwardCompatibilityHelper.Default())
register(FirEnumEntriesSupport::class, FirEnumEntriesSupport(this))
}
}
@@ -7,27 +7,11 @@ package org.jetbrains.kotlin.fir.backend.jvm
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
import org.jetbrains.kotlin.fir.NoMutableState
import org.jetbrains.kotlin.fir.backend.FirBasedKotlinMangler
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.signaturer.FirMangler
@NoMutableState
class FirJvmKotlinMangler : AbstractKotlinMangler<FirDeclaration>(), FirMangler {
override fun FirDeclaration.mangleString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FULL, compatibleMode).computeMangle(this)
override fun FirDeclaration.signatureString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.SIGNATURE, compatibleMode).computeMangle(this)
override fun FirDeclaration.fqnString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FQNAME, compatibleMode).computeMangle(this)
override fun FirDeclaration.isExported(compatibleMode: Boolean): Boolean = true
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<FirDeclaration> {
return object : KotlinExportChecker<FirDeclaration> {
override fun check(declaration: FirDeclaration, type: SpecialDeclarationType): Boolean = true
override fun FirDeclaration.isPlatformSpecificExported(): Boolean = true
}
}
class FirJvmKotlinMangler : FirBasedKotlinMangler() {
override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): KotlinMangleComputer<FirDeclaration> {
return FirJvmMangleComputer(StringBuilder(256), mode)
@@ -5,25 +5,17 @@
package org.jetbrains.kotlin.fir.backend.jvm
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
import org.jetbrains.kotlin.fir.backend.FirMangleComputer
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.signaturer.irName
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.fir.types.coneType
/**
* A mangle computer that generates a mangled name for a Kotlin declaration represented by [FirDeclaration].
@@ -31,20 +23,8 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
class FirJvmMangleComputer(
builder: StringBuilder,
mode: MangleMode,
) : BaseKotlinMangleComputer<
/*Declaration=*/FirDeclaration,
/*Type=*/ConeKotlinType,
/*TypeParameter=*/ConeTypeParameterLookupTag,
/*ValueParameter=*/FirValueParameter,
/*TypeParameterContainer=*/FirMemberDeclaration,
/*FunctionDeclaration=*/FirFunction,
/*Session=*/FirSession,
>(builder, mode) {
override fun getTypeSystemContext(session: FirSession) = object : ConeInferenceContext {
override val session: FirSession
get() = session
}
) : FirMangleComputer(builder, mode) {
override val visitor = JvmVisitor()
override fun FirFunction.platformSpecificSuffix(): String? =
if (this is FirSimpleFunction && name.asString() == "main")
@@ -56,6 +36,7 @@ class FirJvmMangleComputer(
override fun copy(newMode: MangleMode): FirJvmMangleComputer =
FirJvmMangleComputer(builder, newMode)
// FIXME this implementation causes the mangler to deliver different result than IR mangler. Consider using base method instead
override fun FirDeclaration.visitParent() {
val (parentPackageFqName, parentClassId) = when (this) {
is FirCallableDeclaration -> this.containingClassLookupTag()?.classId?.let { it.packageFqName to it } ?: return
@@ -75,71 +56,7 @@ class FirJvmMangleComputer(
}
}
override fun FirDeclaration.visit() {
accept(Visitor(), null)
}
private fun FirFunction.mangleFunction(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
isRealExpect = isRealExpect || (this as? FirMemberDeclaration)?.isExpect == true
if (container is FirMemberDeclaration) {
typeParameterContainers.add(container)
}
visitParent()
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
platformSpecificFunctionName()?.let {
builder.append(it)
return
}
val name = this.irName
builder.append(name.asString())
platformSpecificSuffix()?.let {
builder.append(MangleConstant.PLATFORM_FUNCTION_MARKER)
builder.append(it)
}
mangleSignature(isCtor, isStatic, container)
}
private fun FirFunction.mangleSignature(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
if (!mode.signature) {
return
}
if (isStatic) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
contextReceivers.forEach {
builder.appendSignature(MangleConstant.CONTEXT_RECEIVER_PREFIX)
mangleType(builder, it.typeRef.coneType, moduleData.session)
}
val receiverType = receiverParameter?.typeRef ?: (this as? FirPropertyAccessor)?.propertySymbol?.fir?.receiverParameter?.typeRef
receiverType?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleType(builder, it.coneType, moduleData.session)
}
valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
appendSignature(specialValueParamPrefix(it))
mangleValueParameter(this, it, moduleData.session)
}
(container as? FirTypeParametersOwner)?.typeParameters?.withIndex()?.toList().orEmpty()
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, moduleData.session)
}
if (!isCtor && !returnTypeRef.isUnit && addReturnType()) {
mangleType(builder, returnTypeRef.coneType, moduleData.session)
}
}
// FIXME this implementation causes the mangler to deliver different result than IR mangler. Consider using base method instead
override fun getEffectiveParent(typeParameter: ConeTypeParameterLookupTag): FirMemberDeclaration = typeParameter.symbol.fir.run {
fun FirTypeParameter.sameAs(other: FirTypeParameter) =
@@ -161,124 +78,7 @@ class FirJvmMangleComputer(
throw IllegalStateException("Should not be here!")
}
override fun renderDeclaration(declaration: FirDeclaration) = declaration.render()
override fun getTypeParameterName(typeParameter: ConeTypeParameterLookupTag) = typeParameter.name.asString()
override fun isVararg(valueParameter: FirValueParameter) = valueParameter.isVararg
override fun getValueParameterType(valueParameter: FirValueParameter) = valueParameter.returnTypeRef.coneType
override fun getIndexOfTypeParameter(typeParameter: ConeTypeParameterLookupTag, container: FirMemberDeclaration) =
container.typeParameters.indexOf(typeParameter.symbol.fir)
override fun mangleType(tBuilder: StringBuilder, type: ConeKotlinType, declarationSiteSession: FirSession) {
when (type) {
is ConeLookupTagBasedType -> {
when (val symbol = type.lookupTag.toSymbol(declarationSiteSession)) {
is FirTypeAliasSymbol -> {
mangleType(tBuilder, type.fullyExpandedType(declarationSiteSession), declarationSiteSession)
return
}
is FirClassSymbol -> with(copy(MangleMode.FQNAME)) { symbol.fir.visit() }
is FirTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(symbol.toLookupTag())
// This is performed for a case with invisible class-like symbol in fake override
null -> (type.lookupTag as? ConeClassLikeLookupTag)?.let {
tBuilder.append(it.classId)
}
}
mangleTypeArguments(tBuilder, type, declarationSiteSession)
if (type.isMarkedNullable) {
tBuilder.appendSignature(MangleConstant.Q_MARK)
}
if (type.hasEnhancedNullability) {
tBuilder.appendSignature(MangleConstant.ENHANCED_NULLABILITY_MARK)
}
}
is ConeRawType -> {
mangleType(tBuilder, type.lowerBound, declarationSiteSession)
}
is ConeFlexibleType -> {
with(declarationSiteSession.typeContext) {
// Need to reproduce type approximation done for flexible types in TypeTranslator.
// For now, we replicate the current behaviour of Fir2IrTypeConverter and just take the upper bound
val upper = type.upperBound
if (upper is ConeClassLikeType) {
val lower = type.lowerBound as? ConeClassLikeType ?: error("Expecting class-like type, got ${type.lowerBound}")
val intermediate = if (lower.lookupTag == upper.lookupTag) {
lower.replaceArguments(upper.getArguments())
} else lower
val mixed = if (upper.isNullable) intermediate.makeNullable() else intermediate.makeDefinitelyNotNullOrNotNull()
mangleType(tBuilder, mixed as ConeKotlinType, declarationSiteSession)
} else mangleType(tBuilder, upper, declarationSiteSession)
}
}
is ConeDefinitelyNotNullType -> {
// E.g. not-null type parameter in Java
mangleType(tBuilder, type.original, declarationSiteSession)
}
is ConeCapturedType -> {
mangleType(tBuilder, type.lowerType ?: type.constructor.supertypes!!.first(), declarationSiteSession)
}
is ConeIntersectionType -> {
// TODO: add intersectionTypeApproximation
mangleType(tBuilder, type.intersectedTypes.first(), declarationSiteSession)
}
else -> error("Unexpected type $type")
}
}
private inner class Visitor : FirVisitorVoid() {
override fun visitElement(element: FirElement) = error("unexpected element ${element.render()}")
override fun visitRegularClass(regularClass: FirRegularClass) {
isRealExpect = isRealExpect or regularClass.isExpect
typeParameterContainers.add(regularClass)
regularClass.mangleSimpleDeclaration(regularClass.name.asString())
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) {
anonymousObject.mangleSimpleDeclaration("<anonymous>")
}
override fun visitVariable(variable: FirVariable) {
isRealExpect = isRealExpect or variable.isExpect
typeParameterContainers.add(variable)
variable.visitParent()
val isStaticProperty = variable.isStatic
if (isStaticProperty) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
variable.receiverParameter?.typeRef?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleType(builder, it.coneType, variable.moduleData.session)
}
variable.typeParameters.withIndex().toList()
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, variable.moduleData.session)
}
builder.append(variable.name.asString())
}
override fun visitProperty(property: FirProperty) {
visitVariable(property)
}
protected inner class JvmVisitor : Visitor() {
override fun visitField(field: FirField) {
if (field is FirJavaField) {
field.mangleSimpleDeclaration(field.name.asString())
@@ -286,30 +86,5 @@ class FirJvmMangleComputer(
visitVariable(field)
}
}
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
enumEntry.mangleSimpleDeclaration(enumEntry.name.asString())
}
override fun visitTypeAlias(typeAlias: FirTypeAlias) =
typeAlias.mangleSimpleDeclaration(typeAlias.name.asString())
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
isRealExpect = isRealExpect || simpleFunction.isExpect
val isStatic = simpleFunction.isStatic
simpleFunction.mangleFunction(false, isStatic, simpleFunction)
}
override fun visitConstructor(constructor: FirConstructor) =
constructor.mangleFunction(isCtor = true, isStatic = false, constructor)
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
if (propertyAccessor is FirSyntheticPropertyAccessor) {
// No need to distinguish between the accessor and its delegate.
visitSimpleFunction(propertyAccessor.delegate)
} else {
propertyAccessor.mangleFunction(isCtor = false, propertyAccessor.isStatic, propertyAccessor.propertySymbol.fir)
}
}
}
}
@@ -0,0 +1,31 @@
/*
* 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
import org.jetbrains.kotlin.backend.common.serialization.mangle.AbstractKotlinMangler
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.signaturer.FirMangler
abstract class FirBasedKotlinMangler : AbstractKotlinMangler<FirDeclaration>(), FirMangler {
override fun FirDeclaration.mangleString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FULL, compatibleMode).computeMangle(this)
override fun FirDeclaration.signatureString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.SIGNATURE, compatibleMode).computeMangle(this)
override fun FirDeclaration.fqnString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FQNAME, compatibleMode).computeMangle(this)
override fun FirDeclaration.isExported(compatibleMode: Boolean): Boolean = true
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<FirDeclaration> {
return object : KotlinExportChecker<FirDeclaration> {
override fun check(declaration: FirDeclaration, type: SpecialDeclarationType): Boolean = true
override fun FirDeclaration.isPlatformSpecificExported(): Boolean = true
}
}
}
@@ -0,0 +1,66 @@
/*
* 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
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType
import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.isAnonymous
import org.jetbrains.kotlin.backend.common.serialization.mangle.publishedApiAnnotation
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.resolve.firClassLike
import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration
import org.jetbrains.kotlin.fir.resolve.providers.toSymbol
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.ClassId
abstract class FirExportCheckerVisitor : FirVisitor<Boolean, SpecialDeclarationType>(), KotlinExportChecker<FirDeclaration> {
override fun check(declaration: FirDeclaration, type: SpecialDeclarationType): Boolean =
declaration.accept(this, type)
override fun visitElement(element: FirElement, data: SpecialDeclarationType): Boolean =
TODO("Should have not been reached")
private fun <D> D.globalMemberIsExported(): Boolean where D : FirMemberDeclaration {
val visibility = visibility
if (visibility.isPublicAPI || visibility === Visibilities.Internal) return true
if (visibility === Visibilities.Local) return false
return annotations.hasAnnotation(ClassId.topLevel(publishedApiAnnotation), moduleData.session) || isPlatformSpecificExported()
}
private fun <D> D.isExported(): Boolean where D : FirCallableDeclaration {
val classId = symbol.callableId.classId ?: return globalMemberIsExported()
return visibility !== Visibilities.Local &&
classId.toSymbol(moduleData.session)!!.fir.accept(this@FirExportCheckerVisitor, SpecialDeclarationType.REGULAR)
}
private fun <D> D.isExported(): Boolean where D : FirClassLikeDeclaration {
val containingDeclaration = getContainingDeclaration(moduleData.session) ?: return globalMemberIsExported()
return visibility !== Visibilities.Local &&
containingDeclaration.accept(this@FirExportCheckerVisitor, SpecialDeclarationType.REGULAR)
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: SpecialDeclarationType): Boolean =
!simpleFunction.name.isAnonymous && simpleFunction.isExported()
override fun visitRegularClass(regularClass: FirRegularClass, data: SpecialDeclarationType): Boolean {
if (data == SpecialDeclarationType.ANON_INIT) return false
if (regularClass.name.isAnonymous) return false
return regularClass.isExported()
}
override fun visitConstructor(constructor: FirConstructor, data: SpecialDeclarationType): Boolean {
return constructor.returnTypeRef.firClassLike(constructor.moduleData.session)!!.isExported()
}
override fun visitProperty(property: FirProperty, data: SpecialDeclarationType): Boolean = property.isExported()
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: SpecialDeclarationType): Boolean = false
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: SpecialDeclarationType): Boolean = false
}
@@ -0,0 +1,292 @@
/*
* 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
import org.jetbrains.kotlin.backend.common.serialization.mangle.BaseKotlinMangleComputer
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
import org.jetbrains.kotlin.backend.common.serialization.mangle.collectForMangler
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.signaturer.irName
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
/**
* A base mangle computer that generates a mangled name for a Kotlin declaration represented by [FirDeclaration].
*/
open class FirMangleComputer(
builder: StringBuilder,
mode: MangleMode,
) : BaseKotlinMangleComputer<
/*Declaration=*/FirDeclaration,
/*Type=*/ConeKotlinType,
/*TypeParameter=*/ConeTypeParameterLookupTag,
/*ValueParameter=*/FirValueParameter,
/*TypeParameterContainer=*/FirMemberDeclaration,
/*FunctionDeclaration=*/FirFunction,
/*Session=*/FirSession,
>(builder, mode) {
protected open val visitor = Visitor()
override fun copy(newMode: MangleMode): FirMangleComputer =
FirMangleComputer(builder, newMode)
override fun getTypeSystemContext(session: FirSession) = object : ConeInferenceContext {
override val session: FirSession
get() = session
}
@OptIn(SymbolInternals::class)
override fun FirDeclaration.visitParent() {
val (parentPackageFqName, parentClassId) = when (this) {
is FirCallableDeclaration -> this.symbol.callableId.packageName.let { it to containingClassLookupTag()?.classId }
is FirClassLikeDeclaration -> this.symbol.classId.let { it.packageFqName to it.outerClassId }
else -> return
}
if (parentClassId != null && !parentClassId.isLocal) {
val parentClassLike = this.moduleData.session.symbolProvider.getClassLikeSymbolByClassId(parentClassId)?.fir
?: error("Attempt to find parent ($parentClassId) for probably-local declaration!")
if (parentClassLike is FirRegularClass || parentClassLike is FirTypeAlias) {
parentClassLike.visit()
} else {
error("Strange class-like declaration: ${parentClassLike.render()}")
}
} else if (parentClassId == null && !parentPackageFqName.isRoot) {
builder.appendName(parentPackageFqName.asString())
}
}
override fun FirDeclaration.visit() {
accept(visitor, null)
}
private fun FirFunction.mangleFunction(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
isRealExpect = isRealExpect || (this as? FirMemberDeclaration)?.isExpect == true
if (container is FirMemberDeclaration) {
typeParameterContainers.add(container)
}
visitParent()
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
platformSpecificFunctionName()?.let {
builder.append(it)
return
}
val name = this.irName
builder.append(name.asString())
platformSpecificSuffix()?.let {
builder.append(MangleConstant.PLATFORM_FUNCTION_MARKER)
builder.append(it)
}
mangleSignature(isCtor, isStatic, container)
}
private fun FirFunction.mangleSignature(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
if (!mode.signature) {
return
}
if (isStatic) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
contextReceivers.forEach {
builder.appendSignature(MangleConstant.CONTEXT_RECEIVER_PREFIX)
mangleType(builder, it.typeRef.coneType, moduleData.session)
}
val receiverType = receiverParameter?.typeRef ?: (this as? FirPropertyAccessor)?.propertySymbol?.fir?.receiverParameter?.typeRef
receiverType?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleType(builder, it.coneType, moduleData.session)
}
valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
appendSignature(specialValueParamPrefix(it))
mangleValueParameter(this, it, moduleData.session)
}
(container as? FirTypeParametersOwner)?.typeParameters?.withIndex()?.toList().orEmpty()
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, moduleData.session)
}
if (!isCtor && !returnTypeRef.isUnit && addReturnType()) {
mangleType(builder, returnTypeRef.coneType, moduleData.session)
}
}
@OptIn(SymbolInternals::class)
override fun getEffectiveParent(typeParameter: ConeTypeParameterLookupTag): FirMemberDeclaration = typeParameter.symbol.fir.run {
this.containingDeclarationSymbol.fir as FirMemberDeclaration
}
override fun renderDeclaration(declaration: FirDeclaration) = declaration.render()
override fun getTypeParameterName(typeParameter: ConeTypeParameterLookupTag) = typeParameter.name.asString()
override fun isVararg(valueParameter: FirValueParameter) = valueParameter.isVararg
override fun getValueParameterType(valueParameter: FirValueParameter) = valueParameter.returnTypeRef.coneType
override fun getIndexOfTypeParameter(typeParameter: ConeTypeParameterLookupTag, container: FirMemberDeclaration) =
container.typeParameters.indexOf(typeParameter.symbol.fir)
override fun mangleType(tBuilder: StringBuilder, type: ConeKotlinType, declarationSiteSession: FirSession) {
when (type) {
is ConeLookupTagBasedType -> {
when (val symbol = type.lookupTag.toSymbol(declarationSiteSession)) {
is FirTypeAliasSymbol -> {
mangleType(tBuilder, type.fullyExpandedType(declarationSiteSession), declarationSiteSession)
return
}
is FirClassSymbol -> with(copy(MangleMode.FQNAME)) { symbol.fir.visit() }
is FirTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(symbol.toLookupTag())
// This is performed for a case with invisible class-like symbol in fake override
null -> (type.lookupTag as? ConeClassLikeLookupTag)?.let {
tBuilder.append(it.classId)
}
}
mangleTypeArguments(tBuilder, type, declarationSiteSession)
if (type.isMarkedNullable) {
tBuilder.appendSignature(MangleConstant.Q_MARK)
}
if (type.hasEnhancedNullability) {
tBuilder.appendSignature(MangleConstant.ENHANCED_NULLABILITY_MARK)
}
}
is ConeRawType -> {
mangleType(tBuilder, type.lowerBound, declarationSiteSession)
}
is ConeFlexibleType -> {
with(declarationSiteSession.typeContext) {
// Need to reproduce type approximation done for flexible types in TypeTranslator.
// For now, we replicate the current behaviour of Fir2IrTypeConverter and just take the upper bound
val upper = type.upperBound
if (upper is ConeClassLikeType) {
val lower = type.lowerBound as? ConeClassLikeType ?: error("Expecting class-like type, got ${type.lowerBound}")
val intermediate = if (lower.lookupTag == upper.lookupTag) {
lower.replaceArguments(upper.getArguments())
} else lower
val mixed = if (upper.isNullable) intermediate.makeNullable() else intermediate.makeDefinitelyNotNullOrNotNull()
mangleType(tBuilder, mixed as ConeKotlinType, declarationSiteSession)
} else mangleType(tBuilder, upper, declarationSiteSession)
}
}
is ConeDefinitelyNotNullType -> {
// E.g. not-null type parameter in Java
mangleType(tBuilder, type.original, declarationSiteSession)
}
is ConeCapturedType -> {
mangleType(tBuilder, type.lowerType ?: type.constructor.supertypes!!.first(), declarationSiteSession)
}
is ConeIntersectionType -> {
// TODO: add intersectionTypeApproximation
mangleType(tBuilder, type.intersectedTypes.first(), declarationSiteSession)
}
else -> error("Unexpected type $type")
}
}
protected open inner class Visitor : FirVisitorVoid() {
override fun visitElement(element: FirElement) = error("unexpected element ${element.render()}")
override fun visitRegularClass(regularClass: FirRegularClass) {
isRealExpect = isRealExpect or regularClass.isExpect
typeParameterContainers.add(regularClass)
regularClass.mangleSimpleDeclaration(regularClass.name.asString())
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) {
anonymousObject.mangleSimpleDeclaration("<anonymous>")
}
override fun visitVariable(variable: FirVariable) {
isRealExpect = isRealExpect or variable.isExpect
typeParameterContainers.add(variable)
variable.visitParent()
val isStaticProperty = variable.isStatic
if (isStaticProperty) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
variable.receiverParameter?.typeRef?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleType(builder, it.coneType, variable.moduleData.session)
}
variable.typeParameters.withIndex().toList()
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, variable.moduleData.session)
}
builder.append(variable.name.asString())
}
override fun visitProperty(property: FirProperty) {
visitVariable(property)
}
override fun visitField(field: FirField) {
visitVariable(field)
}
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
enumEntry.mangleSimpleDeclaration(enumEntry.name.asString())
}
override fun visitTypeAlias(typeAlias: FirTypeAlias) =
typeAlias.mangleSimpleDeclaration(typeAlias.name.asString())
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
isRealExpect = isRealExpect || simpleFunction.isExpect
val isStatic = simpleFunction.isStatic
simpleFunction.mangleFunction(false, isStatic, simpleFunction)
}
override fun visitConstructor(constructor: FirConstructor) =
constructor.mangleFunction(isCtor = true, isStatic = false, constructor)
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
if (propertyAccessor is FirSyntheticPropertyAccessor) {
// No need to distinguish between the accessor and its delegate.
visitSimpleFunction(propertyAccessor.delegate)
} else {
propertyAccessor.mangleFunction(isCtor = false, propertyAccessor.isStatic, propertyAccessor.propertySymbol.fir)
}
}
}
}
@@ -221,8 +221,6 @@ internal class AdapterGenerator(
isExpect = false,
isFakeOverride = false
).also { irAdapterFunction ->
irAdapterFunction.metadata = FirMetadataSource.Function(firAdaptee)
symbolTable.enterScope(irAdapterFunction)
irAdapterFunction.dispatchReceiverParameter = null
val boundReceiver = boundDispatchReceiver ?: boundExtensionReceiver
@@ -5,10 +5,40 @@
package org.jetbrains.kotlin.fir.signaturer
import org.jetbrains.kotlin.backend.common.serialization.mangle.AbstractKotlinMangler
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinMangleComputer
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrMetadataSourceOwner
import org.jetbrains.kotlin.ir.util.KotlinMangler
interface FirMangler : KotlinMangler<FirDeclaration> {
override val manglerName: String
get() = "Fir"
}
class Ir2FirManglerAdapter(private val delegate: FirMangler) : AbstractKotlinMangler<IrDeclaration>(),
KotlinMangler.IrMangler {
override val manglerName: String
get() = delegate.manglerName
private fun IrDeclaration.fir(): FirDeclaration = ((this as IrMetadataSourceOwner).metadata as FirMetadataSource).fir!!
override fun IrDeclaration.isExported(compatibleMode: Boolean): Boolean = delegate.run { fir().isExported(compatibleMode) }
override fun IrDeclaration.mangleString(compatibleMode: Boolean): String = delegate.run { fir().mangleString(compatibleMode) }
override fun IrDeclaration.signatureString(compatibleMode: Boolean): String = delegate.run { fir().signatureString(compatibleMode) }
override fun IrDeclaration.fqnString(compatibleMode: Boolean): String = delegate.run { fir().fqnString(compatibleMode) }
override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): KotlinMangleComputer<IrDeclaration> =
error("Should not have been reached")
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<IrDeclaration> {
error("Should not be called")
}
}
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
/**
* That class is expected to work just the same as FirStandardOverrideChecker for regular members,
@@ -20,7 +19,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
* while in Java class they would be treated equally.
*/
class FirIntersectionScopeOverrideChecker(session: FirSession) : FirOverrideChecker {
private val standardOverrideChecker = FirStandardOverrideChecker(session)
private val standardOverrideChecker = session.firOverrideChecker
private val platformSpecificOverridabilityRules = session.platformSpecificOverridabilityRules
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
@@ -5,12 +5,14 @@
package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
interface FirOverrideChecker {
interface FirOverrideChecker : FirSessionComponent {
fun isOverriddenFunction(
overrideCandidate: FirSimpleFunction,
baseDeclaration: FirSimpleFunction
@@ -26,3 +28,5 @@ fun FirOverrideChecker.isOverriddenFunction(
overrideCandidate: FirNamedFunctionSymbol,
baseDeclaration: FirNamedFunctionSymbol
): Boolean = isOverriddenFunction(overrideCandidate.fir, baseDeclaration.fir)
val FirSession.firOverrideChecker: FirOverrideChecker by FirSession.sessionComponentAccessor()
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.firOverrideChecker
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.Name
@@ -23,7 +24,7 @@ class FirClassUseSiteMemberScope(
) : AbstractFirUseSiteMemberScope(
klass.classId,
session,
FirStandardOverrideChecker(session),
session.firOverrideChecker,
superTypeScopes,
klass.defaultType(),
declaredMemberScope
@@ -37,7 +37,7 @@ class FirDelegatedMemberScope(
private val delegateFields: List<FirField>,
) : FirContainingNamesAwareScope() {
private val dispatchReceiverType = containingClass.defaultType()
private val overrideChecker = FirStandardOverrideChecker(session)
private val overrideChecker = session.firOverrideChecker
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
declaredMemberScope.processFunctionsByName(name, processor)
@@ -15,7 +15,15 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.name.SpecialNames
class ManglerChecker(vararg _manglers: KotlinMangler<IrDeclaration>) : IrElementVisitorVoid {
class ManglerChecker(
vararg _manglers: KotlinMangler<IrDeclaration>,
private val needsChecking: (IrDeclarationBase) -> Boolean = hasDescriptor
) : IrElementVisitorVoid {
companion object {
val hasDescriptor: (IrDeclarationBase) -> Boolean = { it.symbol.hasDescriptor }
val hasMetadata: (IrDeclarationBase) -> Boolean = { (it as? IrMetadataSourceOwner)?.metadata != null }
}
private val manglers = _manglers.toList()
@@ -29,7 +37,7 @@ class ManglerChecker(vararg _manglers: KotlinMangler<IrDeclaration>) : IrElement
}
override fun visitDeclaration(declaration: IrDeclarationBase, data: Nothing?): Boolean {
if (!declaration.symbol.hasDescriptor) return true
if (!needsChecking(declaration)) return true
if (declaration.parent is IrPackageFragment) {
val vis = declaration as IrDeclarationWithVisibility
@@ -87,7 +95,7 @@ class ManglerChecker(vararg _manglers: KotlinMangler<IrDeclaration>) : IrElement
if (declaration is IrErrorDeclaration) return
val exported = manglers.checkAllEqual(false, { isExportCheck(declaration) }) { m1, r1, m2, r2 ->
error("${declaration.render()}\n ${m1.manglerName}: $r1\n ${m2.manglerName}: $r2\n")
error("isExportCheck: ${declaration.render()}\n ${m1.manglerName}: $r1\n ${m2.manglerName}: $r2\n")
}
if (!exported) return
@@ -36,4 +36,4 @@ fun <T> Iterable<T>.collectForMangler(builder: StringBuilder, params: MangleCons
builder.append(params.suffix)
}
internal val publishedApiAnnotation = FqName("kotlin.PublishedApi")
val publishedApiAnnotation = FqName("kotlin.PublishedApi")