From 5f5b32b8aebd96608ad83ea06cf1affb8a738a47 Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Wed, 10 May 2023 14:47:16 +0200 Subject: [PATCH] [IR] Add kdocs for IrSymbol-related classes and interfaces --- .../kotlin/ir/symbols/IrDelegatingSymbol.kt | 16 ++ .../jetbrains/kotlin/ir/symbols/IrSymbol.kt | 175 +++++++++++++++++- .../ir/symbols/impl/IrPrivateSymbolBase.kt | 7 + .../ir/symbols/impl/IrPublicSymbolBase.kt | 7 + 4 files changed, 204 insertions(+), 1 deletion(-) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrDelegatingSymbol.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrDelegatingSymbol.kt index e9211a84307..b0860cd253f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrDelegatingSymbol.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrDelegatingSymbol.kt @@ -10,6 +10,22 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.util.IdSignature +/** + * Used to handle `expect` declarations. + * + * Before actualization, [delegate] refers to the symbol of the `expect` declaration. After actualization, + * [delegate] is replaced with the symbol of the corresponding `actual` declaration. + * + * A delegating symbol behaves exactly the same as its [delegate]. + * + * [About `expect` and `actual` declarations.](https://kotlinlang.org/docs/multiplatform-connect-to-apis.html) + * + * @property delegate Before actualization — the symbol of the `expect` declaration, + * after actualization — the symbol of the corresponding `actual` declaration. + * + * @see org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.handleExpectActualMapping + * @see org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.finalizeExpectActual + */ abstract class IrDelegatingSymbol(var delegate: DelegateSymbol) : IrBindableSymbol where DelegateSymbol : IrBindableSymbol, Owner : IrSymbolOwner, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt index 36fe89d1bd0..c1efa0ebe70 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt @@ -19,67 +19,200 @@ package org.jetbrains.kotlin.ir.symbols import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock +import org.jetbrains.kotlin.ir.descriptors.IrBasedDeclarationDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrTypeAbbreviation import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeParameterMarker +/** + * A special object that can be used to refer to [IrDeclaration]s and some other entities from IR nodes. + * + * For example, [IrCall] uses [IrSimpleFunctionSymbol] to refer to the [IrSimpleFunction] that is being called. + * + * **Q:** Why not just use the [IrSimpleFunction] class itself? + * + * **A:** Because a symbol, unlike a declaration, can be bound or unbound (see [isBound]). + * + * We need this distinction to work with IR before the linkage phase. In pre-linkage IR the symbols referencing declarations from + * other modules are not yet bound. + * + * During the linkage phase, we collect all the unbound symbols in the IR tree and try to resolve them to the declarations they should + * refer to. For unbound symbols for public declarations from other modules, [signature] is used to resolve those declarations. + * + * @see IdSignature + * @see SymbolTable + */ interface IrSymbol { + + /** + * The declaration that this symbol refers to if it's bound. + * + * If the symbol is unbound, throws [IllegalStateException]. + * + * **Q:** Why we didn't make this property nullable instead of throwing an exception? + * + * **A:** Because we most often need to access a symbol's owner in lowerings, which happen after linkage, at which point all symbols + * should be already bound. Declaring this property nullable would make working with it more difficult most of the time. + */ val owner: IrSymbolOwner + /** + * If [hasDescriptor] is `true`, returns the [DeclarationDescriptor] of the declaration that this symbol was created for. + * Otherwise, returns a dummy [IrBasedDeclarationDescriptor] that serves as a descriptor-like view to [owner]. + */ @ObsoleteDescriptorBasedAPI val descriptor: DeclarationDescriptor + /** + * Returns `true` if this symbol was created from a [DeclarationDescriptor] either emitted by the K1 (aka classic) frontend, + * or from deserialized metadata. + * + * @see descriptor + */ @ObsoleteDescriptorBasedAPI val hasDescriptor: Boolean + /** + * Whether this symbol has already been resolved to its [owner]. + */ val isBound: Boolean + /** + * If this symbol refers to a publicly accessible declaration (from the binary artifact point of view), + * returns the binary signature of that declaration. + * + * Otherwise, returns `null`. + * + * @see IdSignature.isPubliclyVisible + */ val signature: IdSignature? // TODO: remove once JS IR IC migrates to a different stable tag generation scheme // Used to store signatures in private symbols for JS IC + /** + * If this symbol refers to a local declaration, the signature of that declaration, otherwise `null`. + * + * @see IdSignature.isPubliclyVisible + */ var privateSignature: IdSignature? } +/** + * Whether this symbol refers to a publicly accessible declaration (from the binary artifact point of view). + * + * The symbol doesn't have to be bound. + */ val IrSymbol.isPublicApi: Boolean get() = signature != null +/** + * A stricter-typed [IrSymbol] that allows to set the owner using the [bind] method. The owner can be set only once. + * + * In fact, any [IrSymbol] is [IrBindableSymbol], but having a non-generic interface like [IrSymbol] is sometimes useful. + * + * Only leaf interfaces in the symbol hierarchy inherit from this interface. + */ interface IrBindableSymbol : IrSymbol { override val owner: Owner @ObsoleteDescriptorBasedAPI override val descriptor: Descriptor + /** + * Sets this symbol's owner. + * + * Throws [IllegalStateException] if this symbol has already been bound. + */ fun bind(owner: Owner) } +/** + * A symbol whose [owner] is either [IrFile] or [IrExternalPackageFragment]. + */ sealed interface IrPackageFragmentSymbol : IrSymbol { @ObsoleteDescriptorBasedAPI override val descriptor: PackageFragmentDescriptor } +/** + * A symbol whose [owner] is [IrFile]. Such a symbol is always module-private. + * + * [IrFileSymbol] is never actually serialized, but is useful for deserializing private top-level declarations. + * + * @see IdSignature.FileSignature + */ interface IrFileSymbol : IrPackageFragmentSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrExternalPackageFragment]. + */ interface IrExternalPackageFragmentSymbol : IrPackageFragmentSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrAnonymousInitializer]. + * + * It's not very useful on its own, but since [IrAnonymousInitializer] is an [IrDeclaration], and [IrDeclaration]s must have symbols, + * here we are. + * + * This symbol is never public (wrt linkage). + */ interface IrAnonymousInitializerSymbol : IrBindableSymbol +/** + * A symbol whose [owner] is [IrEnumEntry]. + * + * @see IrGetEnumValue + */ interface IrEnumEntrySymbol : IrBindableSymbol +/** + * A symbol whose [owner] is [IrField]. + * + * @see IrGetField + * @see IrSetField + */ interface IrFieldSymbol : IrBindableSymbol +/** + * A symbol whose [owner] is [IrClass], [IrScript] or [IrTypeParameter]. + * + * @see IrSimpleType + * @see IrClassReference + */ sealed interface IrClassifierSymbol : IrSymbol, TypeConstructorMarker { @ObsoleteDescriptorBasedAPI override val descriptor: ClassifierDescriptor } +/** + * A symbol whose [owner] is [IrClass]. + * + * @see IrClass.sealedSubclasses + * @see IrCall.superQualifierSymbol + * @see IrFieldAccessExpression.superQualifierSymbol + */ interface IrClassSymbol : IrClassifierSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrScript]. + */ interface IrScriptSymbol : IrClassifierSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrTypeParameter]. + */ interface IrTypeParameterSymbol : IrClassifierSymbol, IrBindableSymbol, TypeParameterMarker +/** + * A symbol whose [owner] is [IrValueParameter] or [IrVariable]. + * + * @see IrGetValue + * @see IrSetValue + */ sealed interface IrValueSymbol : IrSymbol { @ObsoleteDescriptorBasedAPI override val descriptor: ValueDescriptor @@ -87,10 +220,21 @@ sealed interface IrValueSymbol : IrSymbol { override val owner: IrValueDeclaration } +/** + * A symbol whose [owner] is [IrValueParameter]. + */ interface IrValueParameterSymbol : IrValueSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrVariable]. + */ interface IrVariableSymbol : IrValueSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrFunction] or [IrReturnableBlock]. + * + * @see IrReturn + */ sealed interface IrReturnTargetSymbol : IrSymbol { @ObsoleteDescriptorBasedAPI override val descriptor: FunctionDescriptor @@ -98,18 +242,47 @@ sealed interface IrReturnTargetSymbol : IrSymbol { override val owner: IrReturnTarget } +/** + * A symbol whose [owner] is [IrConstructor] or [IrSimpleFunction]. + * + * @see IrFunctionReference + */ sealed interface IrFunctionSymbol : IrReturnTargetSymbol { override val owner: IrFunction } +/** + * A symbol whose [owner] is [IrConstructor]. + * + * @see IrConstructorCall + */ interface IrConstructorSymbol : IrFunctionSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrSimpleFunction]. + * + * @see IrCall + */ interface IrSimpleFunctionSymbol : IrFunctionSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrReturnableBlock]. + */ interface IrReturnableBlockSymbol : IrReturnTargetSymbol, IrBindableSymbol +/** + * A symbol whose [owner] is [IrProperty]. + */ interface IrPropertySymbol : IrBindableSymbol +/** + * A symbol whose [owner] is [IrLocalDelegatedProperty]. + */ interface IrLocalDelegatedPropertySymbol : IrBindableSymbol +/** + * A symbol whose [owner] is [IrTypeAlias]. + * + * @see IrTypeAbbreviation + */ interface IrTypeAliasSymbol : IrBindableSymbol diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPrivateSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPrivateSymbolBase.kt index f26c8f28dae..a47fcf301ad 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPrivateSymbolBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPrivateSymbolBase.kt @@ -14,6 +14,13 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.render +/** + * The base class for all non-public (wrt linkage) symbols. + * + * Its [signature] is always `null`. + * + * TODO: Merge with [IrPublicSymbolBase] ([KT-44721](https://youtrack.jetbrains.com/issue/KT-44721)) + */ @OptIn(ObsoleteDescriptorBasedAPI::class) abstract class IrSymbolBase( private val _descriptor: Descriptor? diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt index 3df73605726..7bbbca7e4ba 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt @@ -13,6 +13,13 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.render +/** + * The base class for all public (wrt linkage) symbols. + * + * Its [signature] is never `null`. + * + * TODO: Merge with [IrSymbolBase] ([KT-44721](https://youtrack.jetbrains.com/issue/KT-44721)) + */ abstract class IrPublicSymbolBase( override val signature: IdSignature, private val _descriptor: Descriptor?