From 4986cb14aabd5fb37e2e8756e016c0d385319320 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 7 Jul 2023 10:37:08 +0300 Subject: [PATCH] [IR] Extract descriptor part from SymbolTable into separate component After this change SymbolTable (and ReferenceSymbolTable) contains only methods with IdSignatures. All descriptors-related methods are moved into DescriptorSymbolTableExtension, which automatically delegates to the SymbolTable if needed At this moment there are cross-references between SymbolTable, because descriptor API is still actively used across backends. So SymbolTable is accessible in some place then descriptor extension will be accessible too DescriptorSymbolTableExtension is an implementation of abstract SymbolTableExtension which allows to implement different kinds of storages, e.g. FIR based (it probably will be needed for FIR2IR) --- .../descriptors/IrBuiltInsOverDescriptors.kt | 4 +- .../IrDescriptorBasedFunctionFactory.kt | 4 +- .../psi2ir/generators/ClassGenerator.kt | 2 +- .../psi2ir/generators/DeclarationGenerator.kt | 2 +- .../generators/DelegatedPropertyGenerator.kt | 4 +- .../psi2ir/generators/FunctionGenerator.kt | 2 +- .../psi2ir/generators/PropertyGenerator.kt | 2 +- .../ReflectionReferencesGenerator.kt | 2 +- .../psi2ir/generators/ScriptGenerator.kt | 2 +- .../StandaloneDeclarationGenerator.kt | 6 +- .../generators/TryCatchExpressionGenerator.kt | 2 +- .../FragmentCompilerSymbolTableDecorator.kt | 3 +- .../fragments/FragmentDeclarationGenerator.kt | 8 +- .../kotlin/ir/ObsoleteDescriptorBasedAPI.kt | 9 +- .../ir/util/DeclarationStubGenerator.kt | 8 +- .../ir/util/DescriptorSymbolTableExtension.kt | 498 +++++ .../ir/util/ExternalDependenciesGenerator.kt | 4 +- .../kotlin/ir/util/ReferenceSymbolTable.kt | 63 + .../jetbrains/kotlin/ir/util/SymbolTable.kt | 1607 +++++++---------- .../kotlin/ir/util/SymbolTableExtension.kt | 695 +++++++ .../kotlin/ir/util/SymbolTableSlice.kt | 195 ++ .../backend/common/linkage/issues/checks.kt | 5 +- .../PartialLinkageSupportForLinkerImpl.kt | 3 +- .../IncrementalCompilationSupport.kt | 4 +- .../backend/handlers/IrInlineBodiesHandler.kt | 5 +- ...BuiltInFictitiousFunctionIrClassFactory.kt | 2 +- .../jetbrains/kotlin/backend/konan/Fir2Ir.kt | 4 +- .../interop/DescriptorToIrTranslationUtils.kt | 8 +- .../ir/interop/cenum/CEnumClassGenerator.kt | 2 +- .../cstruct/CStructVarClassGenerator.kt | 2 +- 30 files changed, 2117 insertions(+), 1040 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DescriptorSymbolTableExtension.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ReferenceSymbolTable.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTableExtension.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTableSlice.kt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrBuiltInsOverDescriptors.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrBuiltInsOverDescriptors.kt index ef4511cd3a2..c9cb6682df3 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrBuiltInsOverDescriptors.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrBuiltInsOverDescriptors.kt @@ -85,7 +85,9 @@ class IrBuiltInsOverDescriptors( override val operatorsPackageFragment: IrExternalPackageFragment = IrExternalPackageFragmentImpl(symbolTable.referenceExternalPackageFragment(packageFragmentDescriptor), KOTLIN_INTERNAL_IR_FQN) - private fun ClassDescriptor.toIrSymbol() = symbolTable.referenceClass(this) + private fun ClassDescriptor.toIrSymbol(): IrClassSymbol { + return symbolTable.referenceClass(this) + } private fun KotlinType.toIrType() = typeTranslator.translateType(this) private fun defineOperator( diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrDescriptorBasedFunctionFactory.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrDescriptorBasedFunctionFactory.kt index f325b7b9edc..75ad1495915 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrDescriptorBasedFunctionFactory.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/descriptors/IrDescriptorBasedFunctionFactory.kt @@ -200,7 +200,7 @@ class IrDescriptorBasedFunctionFactory( override fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol { val descriptor = classDescriptor.declaredTypeParameters[index] - return symbolTable.declareGlobalTypeParameter(offset, offset, classOrigin, descriptor, factory).symbol + return symbolTable.descriptorExtension.declareGlobalTypeParameter(descriptor, factory).symbol } override fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor { @@ -444,7 +444,7 @@ class IrDescriptorBasedFunctionFactory( } fun createFakeOverrideProperty(descriptor: PropertyDescriptor): IrProperty { - return symbolTable.declareProperty(offset, offset, memberOrigin, descriptor) { + return symbolTable.declareProperty(descriptor) { irFactory.createProperty( startOffset = offset, endOffset = offset, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt index 469fa9cb3dc..318876bd462 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt @@ -82,7 +82,7 @@ internal class ClassGenerator( it.toIrType() } - irClass.thisReceiver = context.symbolTable.declareValueParameter( + irClass.thisReceiver = context.symbolTable.descriptorExtension.declareValueParameter( startOffset, endOffset, IrDeclarationOrigin.INSTANCE_RECEIVER, classDescriptor.thisAsReceiverParameter, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt index a8b3949486e..b58c43a15d9 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt @@ -144,7 +144,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator { from: List ) { generateTypeParameterDeclarations(irTypeParametersOwner, from) { startOffset, endOffset, typeParameterDescriptor -> - context.symbolTable.declareScopedTypeParameter( + context.symbolTable.descriptorExtension.declareScopedTypeParameter( startOffset, endOffset, IrDeclarationOrigin.DEFINED, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt index dc4f68bb4ec..53c10a79948 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt @@ -263,7 +263,7 @@ internal class DelegatedPropertyGenerator( ): IrLocalDelegatedProperty { val kPropertyType = getKPropertyTypeForLocalDelegatedProperty(variableDescriptor) - val irLocalDelegatedProperty = context.symbolTable.declareLocalDelegatedProperty( + val irLocalDelegatedProperty = context.symbolTable.descriptorExtension.declareLocalDelegatedProperty( ktProperty.startOffsetSkippingComments, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, variableDescriptor, variableDescriptor.type.toIrType() @@ -314,7 +314,7 @@ internal class DelegatedPropertyGenerator( val delegateType = getDelegatedPropertyDelegateType(variableDescriptor, ktDelegate) val delegateDescriptor = createLocalPropertyDelegatedDescriptor(variableDescriptor, delegateType, kPropertyType) - return context.symbolTable.declareVariable( + return context.symbolTable.descriptorExtension.declareVariable( ktDelegate.startOffsetSkippingComments, ktDelegate.endOffset, IrDeclarationOrigin.PROPERTY_DELEGATE, delegateDescriptor, delegateDescriptor.type.toIrType() ).also { irVariable -> diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt index 32a04a925fe..f983307bb4b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt @@ -434,7 +434,7 @@ internal class FunctionGenerator(declarationGenerator: DeclarationGenerator) : D origin = IrDeclarationOrigin.DESTRUCTURED_OBJECT_PARAMETER } } - return context.symbolTable.declareValueParameter( + return context.symbolTable.descriptorExtension.declareValueParameter( ktElement?.pureStartOffset ?: irOwnerElement.startOffset, ktElement?.pureEndOffset ?: irOwnerElement.endOffset, origin, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt index 0031fb36aa0..e22f35011f2 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt @@ -158,7 +158,7 @@ internal class PropertyGenerator(declarationGenerator: DeclarationGenerator) : D propertyDescriptor: PropertyDescriptor, generateInitializer: (IrField) -> IrExpressionBody? ): IrField = - context.symbolTable.declareField( + context.symbolTable.descriptorExtension.declareField( ktPropertyElement.startOffsetSkippingComments, ktPropertyElement.endOffset, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, propertyDescriptor, propertyDescriptor.type.toIrType(), diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt index 7474cf56dc2..0bc1417059c 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt @@ -579,7 +579,7 @@ internal class ReflectionReferencesGenerator(statementGenerator: StatementGenera } else null if (!symbol.isBound) { val offset = UNDEFINED_OFFSET - context.symbolTable.declareProperty(offset, offset, IrDeclarationOrigin.SYNTHETIC_JAVA_PROPERTY_DELEGATE, descriptor) { + context.symbolTable.descriptorExtension.declareProperty(descriptor) { context.irFactory.createProperty( startOffset = offset, endOffset = offset, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ScriptGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ScriptGenerator.kt index 1e59fc8e3be..0ff8f97c89d 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ScriptGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ScriptGenerator.kt @@ -293,7 +293,7 @@ internal class ScriptGenerator(declarationGenerator: DeclarationGenerator) : Dec } private fun ParameterDescriptor.toIrValueParameter(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin) = - context.symbolTable.declareValueParameter( + context.symbolTable.descriptorExtension.declareValueParameter( startOffset, endOffset, origin, this, type.toIrType(), diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt index d8a7183886f..42574c2377d 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt @@ -48,7 +48,7 @@ internal class StandaloneDeclarationGenerator(private val context: GeneratorCont from: List ) { generateTypeParameterDeclarations(irTypeParametersOwner, from) { startOffset, endOffset, typeParameterDescriptor -> - symbolTable.declareScopedTypeParameter(startOffset, endOffset, IrDeclarationOrigin.DEFINED, typeParameterDescriptor) + symbolTable.descriptorExtension.declareScopedTypeParameter(startOffset, endOffset, IrDeclarationOrigin.DEFINED, typeParameterDescriptor) } } @@ -90,7 +90,7 @@ internal class StandaloneDeclarationGenerator(private val context: GeneratorCont it.toIrType() } - irClass.thisReceiver = context.symbolTable.declareValueParameter( + irClass.thisReceiver = context.symbolTable.descriptorExtension.declareValueParameter( startOffset, endOffset, IrDeclarationOrigin.INSTANCE_RECEIVER, descriptor.thisAsReceiverParameter, @@ -134,7 +134,7 @@ internal class StandaloneDeclarationGenerator(private val context: GeneratorCont } protected fun declareParameter(descriptor: ParameterDescriptor, ktElement: KtPureElement?, irOwnerElement: IrElement): IrValueParameter { - return symbolTable.declareValueParameter( + return symbolTable.descriptorExtension.declareValueParameter( ktElement?.pureStartOffset ?: irOwnerElement.startOffset, ktElement?.pureEndOffset ?: irOwnerElement.endOffset, IrDeclarationOrigin.DEFINED, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt index e780543debd..387b1694a75 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt @@ -39,7 +39,7 @@ internal class TryCatchExpressionGenerator(statementGenerator: StatementGenerato val irCatch = IrCatchImpl( ktCatchClause.startOffsetSkippingComments, ktCatchClause.endOffset, - context.symbolTable.declareVariable( + context.symbolTable.descriptorExtension.declareVariable( ktCatchParameter.startOffsetSkippingComments, ktCatchParameter.endOffset, IrDeclarationOrigin.CATCH_PARAMETER, catchParameterDescriptor, catchParameterDescriptor.type.toIrType() diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentCompilerSymbolTableDecorator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentCompilerSymbolTableDecorator.kt index e661e643313..c5e4e920008 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentCompilerSymbolTableDecorator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentCompilerSymbolTableDecorator.kt @@ -51,6 +51,7 @@ class FragmentCompilerSymbolTableDecorator( return super.referenceValueParameter(descriptor) } + override fun referenceValue(value: ValueDescriptor): IrValueSymbol { val fi = fragmentInfo ?: return super.referenceValue(value) @@ -71,4 +72,4 @@ class FragmentCompilerSymbolTableDecorator( return super.referenceValue(value) } -} \ No newline at end of file +} diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentDeclarationGenerator.kt index 40bbc1f7c14..6fb565d2903 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentDeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentDeclarationGenerator.kt @@ -42,7 +42,7 @@ open class FragmentDeclarationGenerator( Modality.FINAL ) }.buildWithScope { irClass -> - irClass.thisReceiver = context.symbolTable.declareValueParameter( + irClass.thisReceiver = context.symbolTable.descriptorExtension.declareValueParameter( startOffset, endOffset, IrDeclarationOrigin.INSTANCE_RECEIVER, classDescriptor.thisAsReceiverParameter, @@ -128,14 +128,14 @@ open class FragmentDeclarationGenerator( // of IR generation. The replacement is delayed because the JVM // specific infrastructure (i.e. "SharedVariableContext") is not yet // instantiated: PSI2IR is kept backend agnostic. - return context.symbolTable.declareValueParameter( + return context.symbolTable.descriptorExtension.declareValueParameter( UNDEFINED_OFFSET, UNDEFINED_OFFSET, if (shouldPromoteToSharedVariable(parameterInfo)) IrDeclarationOrigin.SHARED_VARIABLE_IN_EVALUATOR_FRAGMENT else IrDeclarationOrigin.DEFINED, descriptor, descriptor.type.toIrType(), descriptor.varargElementType?.toIrType(), - null, + name = null, isAssignable = parameterInfo.isLValue ) } @@ -157,4 +157,4 @@ open class FragmentDeclarationGenerator( } } -} \ No newline at end of file +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/ObsoleteDescriptorBasedAPI.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/ObsoleteDescriptorBasedAPI.kt index 5acbb896302..c9c79c00381 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/ObsoleteDescriptorBasedAPI.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/ObsoleteDescriptorBasedAPI.kt @@ -13,5 +13,12 @@ package org.jetbrains.kotlin.ir * However, more correct and universal way is to store all necessary information inside IR elements themselves * and do not use descriptors as some intermediate storage. It's planned to remove all descriptor usages from IR in future. */ +@Target( + AnnotationTarget.CLASS, + AnnotationTarget.PROPERTY, + AnnotationTarget.VALUE_PARAMETER, + AnnotationTarget.FUNCTION, + AnnotationTarget.TYPEALIAS +) @RequiresOptIn(message = "Please use IR declaration properties and not its descriptor properties", level = RequiresOptIn.Level.ERROR) -annotation class ObsoleteDescriptorBasedAPI \ No newline at end of file +annotation class ObsoleteDescriptorBasedAPI diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt index 5a15c88a7cd..b159bb863ed 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt @@ -141,9 +141,7 @@ abstract class DeclarationStubGenerator( } val origin = computeOrigin(descriptor) - return symbolTable.declareProperty( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original, descriptor.isDelegated - ) { + return symbolTable.descriptorExtension.declareProperty(descriptor.original) { IrLazyProperty( UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, descriptor, @@ -294,7 +292,7 @@ abstract class DeclarationStubGenerator( return referenced.owner } val origin = computeOrigin(descriptor) - return symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) { + return symbolTable.declareEnumEntry(descriptor) { IrLazyEnumEntryImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, descriptor, @@ -309,7 +307,7 @@ abstract class DeclarationStubGenerator( return referenced.owner } val origin = computeOrigin(descriptor) - return symbolTable.declareGlobalTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) { + return symbolTable.descriptorExtension.declareGlobalTypeParameter(descriptor) { IrLazyTypeParameter( UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, descriptor, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DescriptorSymbolTableExtension.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DescriptorSymbolTableExtension.kt new file mode 100644 index 00000000000..de732e579fd --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DescriptorSymbolTableExtension.kt @@ -0,0 +1,498 @@ +/* + * 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.ir.util + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrScriptImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.IrBasedClassDescriptor +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.symbols.impl.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal +import org.jetbrains.kotlin.utils.threadLocal + +@ObsoleteDescriptorBasedAPI +typealias DescriptorBasedReferenceSymbolTableExtension = ReferenceSymbolTableExtension< + ClassDescriptor, TypeAliasDescriptor, ScriptDescriptor, FunctionDescriptor, ClassConstructorDescriptor, + PropertyDescriptor, ValueParameterDescriptor, TypeParameterDescriptor + > + +@ObsoleteDescriptorBasedAPI +class DescriptorSymbolTableExtension(table: SymbolTable) : SymbolTableExtension< + DeclarationDescriptor, ClassDescriptor, TypeAliasDescriptor, ScriptDescriptor, FunctionDescriptor, + ClassConstructorDescriptor, PropertyDescriptor, ParameterDescriptor, TypeParameterDescriptor>(table) +{ + private val irFactory: IrFactory + get() = table.irFactory + + private val nameProvider: NameProvider + get() = table.nameProvider + + private val signatureComposer: IdSignatureComposer + get() = table.signaturer + + private val externalPackageFragmentSlice: SymbolTableSlice = SymbolTableSlice.Flat(lock) + + private val valueParameterSlice: SymbolTableSlice.Scoped by threadLocal { + SymbolTableSlice.Scoped(lock) + } + + private val variableSlice: SymbolTableSlice.Scoped by threadLocal { + SymbolTableSlice.Scoped(lock) + } + + private val localDelegatedPropertySlice: SymbolTableSlice.Scoped by threadLocal { + SymbolTableSlice.Scoped(lock) + } + + override fun MutableList>.initializeScopedSlices() { + add(valueParameterSlice) + add(variableSlice) + add(localDelegatedPropertySlice) + } + + // ------------------------------------ signature ------------------------------------ + + override fun calculateSignature(declaration: DeclarationDescriptor): IdSignature? { + return signatureComposer.composeSignature(declaration) + } + + override fun calculateEnumEntrySignature(declaration: ClassDescriptor): IdSignature? { + return signatureComposer.composeEnumEntrySignature(declaration) + } + + override fun calculateFieldSignature(declaration: PropertyDescriptor): IdSignature? { + return signatureComposer.composeFieldSignature(declaration) + } + + // ------------------------------------ script ------------------------------------ + + override fun defaultScriptFactory(startOffset: Int, endOffset: Int, script: ScriptDescriptor, symbol: IrScriptSymbol): IrScript { + return IrScriptImpl(symbol, nameProvider.nameForDeclaration(script), irFactory, startOffset, endOffset) + } + + override fun createScriptSymbol(descriptor: ScriptDescriptor, signature: IdSignature?): IrScriptSymbol { + return IrScriptSymbolImpl(descriptor) + } + + // ------------------------------------ class ------------------------------------ + + override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol { + return if (descriptor is IrBasedClassDescriptor) { + descriptor.owner.symbol + } else { + super.referenceClass(descriptor) + } + } + + fun declareClassFromLinker(descriptor: ClassDescriptor, signature: IdSignature, classFactory: (IrClassSymbol) -> IrClass): IrClass { + return declareFromLinker( + descriptor, + signature, + SymbolTable::declareClass, + ::declareClass, + ::createClassSymbol, + classFactory + ) + } + + override fun createPublicClassSymbol(descriptor: ClassDescriptor, signature: IdSignature): IrClassSymbol { + return IrClassPublicSymbolImpl(signature, descriptor) + } + + override fun createPrivateClassSymbol(descriptor: ClassDescriptor): IrClassSymbol { + return IrClassSymbolImpl(descriptor) + } + + // ------------------------------------ constructor ------------------------------------ + + fun declareConstructorFromLinker( + descriptor: ClassConstructorDescriptor, + signature: IdSignature, + constructorFactory: (IrConstructorSymbol) -> IrConstructor, + ): IrConstructor { + return declareFromLinker( + descriptor, + signature, + SymbolTable::declareConstructor, + ::declareConstructor, + ::createConstructorSymbol, + constructorFactory + ) + } + + override fun createPublicConstructorSymbol(descriptor: ClassConstructorDescriptor, signature: IdSignature): IrConstructorSymbol { + return IrConstructorPublicSymbolImpl(signature, descriptor) + } + + override fun createPrivateConstructorSymbol(descriptor: ClassConstructorDescriptor): IrConstructorSymbol { + return IrConstructorSymbolImpl(descriptor) + } + + // ------------------------------------ enum entry ------------------------------------ + + fun declareEnumEntryFromLinker( + descriptor: ClassDescriptor, + signature: IdSignature, + factory: (IrEnumEntrySymbol) -> IrEnumEntry, + ): IrEnumEntry { + return declareFromLinker( + descriptor, + signature, + SymbolTable::declareEnumEntry, + ::declareEnumEntry, + ::createEnumEntrySymbol, + factory + ) + } + + override fun createPublicEnumEntrySymbol(descriptor: ClassDescriptor, signature: IdSignature): IrEnumEntrySymbol { + return IrEnumEntryPublicSymbolImpl(signature, descriptor) + } + + override fun createPrivateEnumEntrySymbol(descriptor: ClassDescriptor): IrEnumEntrySymbol { + return IrEnumEntrySymbolImpl(descriptor) + } + + override fun defaultEnumEntryFactory( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + enumEntry: ClassDescriptor, + symbol: IrEnumEntrySymbol, + ): IrEnumEntry { + return irFactory.createEnumEntry(startOffset, endOffset, origin, nameProvider.nameForDeclaration(enumEntry), symbol) + } + + // ------------------------------------ field ------------------------------------ + + override fun createPublicFieldSymbol(descriptor: PropertyDescriptor, signature: IdSignature): IrFieldSymbol { + return IrFieldPublicSymbolImpl(signature, descriptor) + } + + override fun createPrivateFieldSymbol(descriptor: PropertyDescriptor): IrFieldSymbol { + return IrFieldSymbolImpl(descriptor) + } + + override fun defaultFieldFactory( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: PropertyDescriptor, + type: IrType, + visibility: DescriptorVisibility?, + symbol: IrFieldSymbol, + ): IrField { + return irFactory.createField( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = nameProvider.nameForDeclaration(descriptor), + visibility = visibility ?: symbol.descriptor.visibility, + symbol = symbol, + type = type, + isFinal = !symbol.descriptor.isVar, + isStatic = symbol.descriptor.dispatchReceiverParameter == null, + isExternal = symbol.descriptor.isEffectivelyExternal(), + ).apply { + metadata = DescriptorMetadataSource.Property(symbol.descriptor) + } + } + + // ------------------------------------ property ------------------------------------ + + fun declarePropertyFromLinker( + descriptor: PropertyDescriptor, + signature: IdSignature, + propertyFactory: (IrPropertySymbol) -> IrProperty, + ): IrProperty { + return declareFromLinker( + descriptor, + signature, + SymbolTable::declareProperty, + ::declareProperty, + ::createPropertySymbol, + propertyFactory + ) + } + + override fun createPublicPropertySymbol(descriptor: PropertyDescriptor, signature: IdSignature): IrPropertySymbol { + return IrPropertyPublicSymbolImpl(signature, descriptor) + } + + override fun createPrivatePropertySymbol(descriptor: PropertyDescriptor): IrPropertySymbol { + return IrPropertySymbolImpl(descriptor) + } + + override fun defaultPropertyFactory( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: PropertyDescriptor, + isDelegated: Boolean, + symbol: IrPropertySymbol, + ): IrProperty { + return irFactory.createProperty( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = nameProvider.nameForDeclaration(descriptor), + visibility = descriptor.visibility, + modality = descriptor.modality, + symbol = symbol, + isVar = descriptor.isVar, + isConst = descriptor.isConst, + isLateinit = descriptor.isLateInit, + isDelegated = isDelegated, + isExternal = descriptor.isEffectivelyExternal(), + isExpect = descriptor.isExpect, + isFakeOverride = descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE, + ).apply { + metadata = DescriptorMetadataSource.Property(symbol.descriptor) + } + } + + // ------------------------------------ typealias ------------------------------------ + + override fun createPublicTypeAliasSymbol(descriptor: TypeAliasDescriptor, signature: IdSignature): IrTypeAliasSymbol { + return IrTypeAliasPublicSymbolImpl(signature, descriptor) + } + + override fun createPrivateTypeAliasSymbol(descriptor: TypeAliasDescriptor): IrTypeAliasSymbol { + return IrTypeAliasSymbolImpl(descriptor) + } + + // ------------------------------------ function ------------------------------------ + + fun declareSimpleFunctionFromLinker( + descriptor: FunctionDescriptor, + signature: IdSignature, + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction, + ): IrSimpleFunction { + return declareFromLinker( + descriptor, + signature, + SymbolTable::declareSimpleFunction, + ::declareSimpleFunction, + ::createFunctionSymbol, + functionFactory + ) + } + + override fun createPublicFunctionSymbol(descriptor: FunctionDescriptor, signature: IdSignature): IrSimpleFunctionSymbol { + return IrSimpleFunctionPublicSymbolImpl(signature, descriptor) + } + + override fun createPrivateFunctionSymbol(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol { + return IrSimpleFunctionSymbolImpl(descriptor) + } + + // ------------------------------------ type parameter ------------------------------------ + + override fun createPublicTypeParameterSymbol(descriptor: TypeParameterDescriptor, signature: IdSignature): IrTypeParameterSymbol { + return IrTypeParameterPublicSymbolImpl(signature, descriptor) + } + + override fun createPrivateTypeParameterSymbol(descriptor: TypeParameterDescriptor): IrTypeParameterSymbol { + return IrTypeParameterSymbolImpl(descriptor) + } + + override fun defaultTypeParameterFactory( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: TypeParameterDescriptor, + symbol: IrTypeParameterSymbol, + ): IrTypeParameter { + return irFactory.createTypeParameter( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = nameProvider.nameForDeclaration(descriptor), + symbol = symbol, + variance = symbol.descriptor.variance, + index = symbol.descriptor.index, + isReified = symbol.descriptor.isReified + ) + } + + // ------------------------------------ package fragment ------------------------------------ + + fun referenceExternalPackageFragment(descriptor: PackageFragmentDescriptor): IrExternalPackageFragmentSymbol = + externalPackageFragmentSlice.referenced(descriptor) { IrExternalPackageFragmentSymbolImpl(descriptor) } + + fun declareExternalPackageFragment(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment { + return externalPackageFragmentSlice.declare( + descriptor, + { IrExternalPackageFragmentSymbolImpl(descriptor) }, + { IrExternalPackageFragmentImpl(it, descriptor.fqName) } + ) + } + + fun declareExternalPackageFragmentIfNotExists(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment { + return externalPackageFragmentSlice.declareIfNotExists( + descriptor, + { IrExternalPackageFragmentSymbolImpl(descriptor) }, + { IrExternalPackageFragmentImpl(it, descriptor.fqName) } + ) + } + + // ------------------------------------ anonymous initializer ------------------------------------ + + fun declareAnonymousInitializer( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: ClassDescriptor + ): IrAnonymousInitializer = + irFactory.createAnonymousInitializer( + startOffset, endOffset, origin, + IrAnonymousInitializerSymbolImpl(descriptor) + ) + + // ------------------------------------ value parameter ------------------------------------ + + fun declareValueParameter( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: ParameterDescriptor, + type: IrType, + varargElementType: IrType? = null, + name: Name? = null, + index: Int? = null, + isAssignable: Boolean = false, + valueParameterFactory: (IrValueParameterSymbol) -> IrValueParameter = { + irFactory.createValueParameter( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = name ?: nameProvider.nameForDeclaration(descriptor), + type = type, + isAssignable = isAssignable, + symbol = it, + index = index ?: descriptor.indexOrMinusOne, + varargElementType = varargElementType, + isCrossinline = descriptor.isCrossinline, + isNoinline = descriptor.isNoinline, + isHidden = false, + ) + } + ): IrValueParameter = + valueParameterSlice.declareLocal( + descriptor, + { IrValueParameterSymbolImpl(descriptor) }, + valueParameterFactory + ) + + @OptIn(ObsoleteDescriptorBasedAPI::class) + fun introduceValueParameter(irValueParameter: IrValueParameter) { + valueParameterSlice.introduceLocal(irValueParameter.descriptor, irValueParameter.symbol) + } + + override fun referenceValueParameter(descriptor: ParameterDescriptor): IrValueParameterSymbol { + return valueParameterSlice.referenced(descriptor) { + error("Undefined parameter referenced: $descriptor\n${valueParameterSlice.dump()}") + } + } + + // TODO: convert to extension + fun referenceValue(value: ValueDescriptor): IrValueSymbol { + return when (value) { + is ParameterDescriptor -> valueParameterSlice.referenced(value) { error("Undefined parameter referenced: $value") } + is VariableDescriptor -> variableSlice.referenced(value) { error("Undefined variable referenced: $value") } + else -> error("Unexpected value descriptor: $value") + } + } + + + // ------------------------------------ variable ------------------------------------ + + fun declareVariable( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: VariableDescriptor, + type: IrType, + ): IrVariable = + variableSlice.declareLocal( + descriptor, + { IrVariableSymbolImpl(descriptor) } + ) { + IrVariableImpl( + startOffset, endOffset, origin, it, nameProvider.nameForDeclaration(descriptor), type, + descriptor.isVar, descriptor.isConst, descriptor.isLateInit + ) + } + + fun declareVariable( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: VariableDescriptor, + type: IrType, + irInitializerExpression: IrExpression? + ): IrVariable = + declareVariable(startOffset, endOffset, origin, descriptor, type).apply { + initializer = irInitializerExpression + } + + // ------------------------------------ local delegated property ------------------------------------ + + fun declareLocalDelegatedProperty( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: VariableDescriptorWithAccessors, + type: IrType + ): IrLocalDelegatedProperty { + return localDelegatedPropertySlice.declareLocal( + descriptor, + { IrLocalDelegatedPropertySymbolImpl(descriptor) }, + ) { + irFactory.createLocalDelegatedProperty( + startOffset = startOffset, + endOffset = endOffset, + origin = origin, + name = nameProvider.nameForDeclaration(descriptor), + symbol = it, + type = type, + isVar = descriptor.isVar + ) + }.apply { + metadata = DescriptorMetadataSource.LocalDelegatedProperty(descriptor) + } + } + + fun referenceLocalDelegatedProperty(descriptor: VariableDescriptorWithAccessors): IrLocalDelegatedPropertySymbol = + localDelegatedPropertySlice.referenced(descriptor) { + error("Undefined local delegated property referenced: $descriptor") + } + + // ------------------------------------ utilities ------------------------------------ + + private inline fun , SymbolOwner : IrSymbolOwner> declareFromLinker( + descriptor: D, + signature: IdSignature, + declareBySignature: SymbolTable.(IdSignature, () -> Symbol, OwnerFactory) -> SymbolOwner, + declareByDescriptor: (D, OwnerFactory) -> SymbolOwner, + crossinline symbolFactory: SymbolFactory, + noinline ownerFactory: OwnerFactory + ): SymbolOwner { + return if (signature.isPubliclyVisible) { + table.declareBySignature(signature, { symbolFactory(descriptor, signature) }, ownerFactory) + } else { + declareByDescriptor(descriptor, ownerFactory) + } + } +} + diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt index 17ff84d6cc1..c288f8ad0c7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt @@ -15,6 +15,7 @@ */ package org.jetbrains.kotlin.ir.util +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.linkage.IrProvider import org.jetbrains.kotlin.ir.symbols.IrSymbol @@ -22,6 +23,7 @@ class ExternalDependenciesGenerator( private val symbolTable: SymbolTable, private val irProviders: List ) { + @OptIn(ObsoleteDescriptorBasedAPI::class) fun generateUnboundSymbolsAsDependencies() { // There should be at most one DeclarationStubGenerator (none in closed world?) irProviders.filterIsInstance().singleOrNull()?.run { unboundSymbolGeneration = true } @@ -30,7 +32,7 @@ class ExternalDependenciesGenerator( var unbound = emptySet() do { val prevUnbound = unbound - unbound = symbolTable.allUnbound + unbound = symbolTable.descriptorExtension.allUnboundSymbols for (symbol in unbound) { // Symbol could get bound as a side effect of deserializing other symbols. if (!symbol.isBound) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ReferenceSymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ReferenceSymbolTable.kt new file mode 100644 index 00000000000..d455b2ec5fa --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ReferenceSymbolTable.kt @@ -0,0 +1,63 @@ +/* + * 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.ir.util + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.symbols.* + +interface ReferenceSymbolTable { + @ObsoleteDescriptorBasedAPI + fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol + fun referenceClass(signature: IdSignature): IrClassSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceScript(descriptor: ScriptDescriptor): IrScriptSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceConstructor(descriptor: ClassConstructorDescriptor): IrConstructorSymbol + fun referenceConstructor(signature: IdSignature): IrConstructorSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol + fun referenceEnumEntry(signature: IdSignature): IrEnumEntrySymbol + + @ObsoleteDescriptorBasedAPI + fun referenceField(descriptor: PropertyDescriptor): IrFieldSymbol + fun referenceField(signature: IdSignature): IrFieldSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceProperty(descriptor: PropertyDescriptor): IrPropertySymbol + fun referenceProperty(signature: IdSignature): IrPropertySymbol + + @ObsoleteDescriptorBasedAPI + fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol + fun referenceSimpleFunction(signature: IdSignature): IrSimpleFunctionSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceDeclaredFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceValueParameter(descriptor: ParameterDescriptor): IrValueParameterSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol + fun referenceTypeParameter(signature: IdSignature): IrTypeParameterSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceScopedTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol + + @ObsoleteDescriptorBasedAPI + fun referenceTypeAlias(descriptor: TypeAliasDescriptor): IrTypeAliasSymbol + fun referenceTypeAlias(signature: IdSignature): IrTypeAliasSymbol + + fun enterScope(symbol: IrSymbol) + fun enterScope(owner: IrDeclaration) + + fun leaveScope(symbol: IrSymbol) + fun leaveScope(owner: IrDeclaration) +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 856759e4e88..a1bbf0d30f2 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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. */ @@ -9,507 +9,60 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrLock import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrScriptImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.lazy.IrLazySymbolTable -import org.jetbrains.kotlin.ir.descriptors.IrBasedClassDescriptor import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal -import org.jetbrains.kotlin.utils.threadLocal - -interface ReferenceSymbolTable { - @ObsoleteDescriptorBasedAPI - fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol - fun referenceClass(signature: IdSignature): IrClassSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceScript(descriptor: ScriptDescriptor): IrScriptSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceConstructor(descriptor: ClassConstructorDescriptor): IrConstructorSymbol - fun referenceConstructor(signature: IdSignature): IrConstructorSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol - fun referenceEnumEntry(signature: IdSignature): IrEnumEntrySymbol - - @ObsoleteDescriptorBasedAPI - fun referenceField(descriptor: PropertyDescriptor): IrFieldSymbol - fun referenceField(signature: IdSignature): IrFieldSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceProperty(descriptor: PropertyDescriptor): IrPropertySymbol - fun referenceProperty(signature: IdSignature): IrPropertySymbol - - @ObsoleteDescriptorBasedAPI - fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol - fun referenceSimpleFunction(signature: IdSignature): IrSimpleFunctionSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceDeclaredFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceValueParameter(descriptor: ParameterDescriptor): IrValueParameterSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol - fun referenceTypeParameter(signature: IdSignature): IrTypeParameterSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceScopedTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol - - @ObsoleteDescriptorBasedAPI - fun referenceTypeAlias(descriptor: TypeAliasDescriptor): IrTypeAliasSymbol - fun referenceTypeAlias(signature: IdSignature): IrTypeAliasSymbol - - fun enterScope(symbol: IrSymbol) - fun enterScope(owner: IrDeclaration) - - fun leaveScope(symbol: IrSymbol) - fun leaveScope(owner: IrDeclaration) -} open class SymbolTable( val signaturer: IdSignatureComposer, val irFactory: IrFactory, - val nameProvider: NameProvider = NameProvider.DEFAULT + val nameProvider: NameProvider = NameProvider.DEFAULT, ) : ReferenceSymbolTable { + val lock: IrLock = IrLock() - val lock = IrLock() + private val scriptSlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) + private val classSlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) + private val constructorSlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) + private val enumEntrySlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) + private val fieldSlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) + private val functionSlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) + private val propertySlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) + private val typeAliasSlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) + private val globalTypeParameterSlice: SymbolTableSlice.Flat = SymbolTableSlice.Flat(lock) @Suppress("LeakingThis") val lazyWrapper = IrLazySymbolTable(this) - @Suppress("DuplicatedCode") - private abstract class SymbolTableBase(val lock: IrLock) - where Descriptor : DeclarationDescriptor, - SymbolOwner : IrSymbolOwner, - Symbol : IrBindableSymbol { - /** - * With the partial linkage turned on it's hard to predict whether a newly created [IrSymbol] that is added to the [SymbolTable] - * via one of referenceXXX() calls will or won't be bound to some declaration. The latter may happen in certain cases, - * for example when the symbol refers from an IR expression to a non-top level declaration that was removed in newer version - * of Kotlin library (KLIB). Unless such symbol is registered as "probably unbound" it remains invisible for the linkage process. - * - * The optimization that allows to reference symbols without registering them as "probably unbound" is fragile. It's better - * to avoid calling any referenceXXX(reg = false) functions. Instead, wherever it is s suitable it is recommended to use one - * of the appropriate declareXXX() calls. - * - * For the future: Consider implementing the optimization once again for the new "flat" ID signatures. - */ - val unboundSymbols = linkedSetOf() + @Suppress("LeakingThis") + @OptIn(ObsoleteDescriptorBasedAPI::class) + val descriptorExtension: DescriptorSymbolTableExtension = DescriptorSymbolTableExtension(this) - protected abstract fun signature(descriptor: Descriptor): IdSignature? - - // TODO: consider replacing paired get/set calls by java.util.Map.computeIfAbsent() which would be more performant - abstract fun get(descriptor: Descriptor, signature: IdSignature?): Symbol? - abstract fun set(symbol: Symbol) - abstract fun get(signature: IdSignature): Symbol? - abstract fun set(signature: IdSignature, symbol: Symbol) - - inline fun declare( - descriptor: Descriptor, - createSymbol: (IdSignature?) -> Symbol, - createOwner: (Symbol) -> SymbolOwner, - ): SymbolOwner { - synchronized(lock) { - val signature = signature(descriptor) - val existing = get(descriptor, signature) - val symbol = if (existing == null) { - checkOriginal(descriptor) - val new = createSymbol(signature) - set(new) - new - } else { - unboundSymbols.remove(existing) - existing - } - return createOwnerSafe(symbol, createOwner) - } - } - - inline fun declare(signature: IdSignature, createSymbol: () -> Symbol, createOwner: (Symbol) -> SymbolOwner): SymbolOwner { - synchronized(lock) { - val existing = get(signature) - val symbol = if (existing == null) { - createSymbol() - } else { - unboundSymbols.remove(existing) - existing - } - return createOwnerSafe(symbol, createOwner) - .also { - // TODO: try to get rid of this - set(symbol) - } - } - } - - inline fun declareIfNotExists( - descriptor: Descriptor, - createSymbol: (IdSignature?) -> Symbol, - createOwner: (Symbol) -> SymbolOwner, - ): SymbolOwner { - synchronized(lock) { - val signature = signature(descriptor) - val existing = get(descriptor, signature) - val symbol = if (existing == null) { - checkOriginal(descriptor) - val new = createSymbol(signature) - set(new) - new - } else { - if (existing.isBound) { - unboundSymbols.remove(existing) - return existing.owner - } - existing - } - return createOwnerSafe(symbol, createOwner) - } - } - - inline fun declare( - signature: IdSignature, - descriptor: Descriptor?, - createSymbol: () -> Symbol, - createOwner: (Symbol) -> SymbolOwner, - ): SymbolOwner { - synchronized(lock) { - val existing = get(signature) - val symbol = if (existing == null) { - checkOriginal(descriptor) - val new = createSymbol() - set(new) - new - } else { - unboundSymbols.remove(existing) - existing - } - return createOwnerSafe(symbol, createOwner) - } - } - - inline fun referenced(descriptor: Descriptor, orElse: (IdSignature?) -> Symbol): Symbol { - synchronized(lock) { - val signature = signature(descriptor) - return get(descriptor, signature) ?: run { - checkOriginal(descriptor) - val new = orElse(signature) - assert(unboundSymbols.add(new)) { "Symbol for $new was already referenced" } - set(new) - new - } - } - } - - inline fun referenced(signature: IdSignature, orElse: () -> Symbol): Symbol { - synchronized(lock) { - return get(signature) ?: run { - val new = orElse() - assert(unboundSymbols.add(new)) { "Symbol for ${new.signature} was already referenced" } - set(new) - new - } - } - } - - private fun checkOriginal(descriptor: Descriptor?) { - @Suppress("UNCHECKED_CAST") - val descriptor0 = descriptor?.original as Descriptor - assert(descriptor0 === descriptor) { - "Non-original descriptor in declaration: $descriptor\n\tExpected: $descriptor0" - } - } - - protected inline fun createOwnerSafe(symbol: Symbol, createOwner: (Symbol) -> SymbolOwner): SymbolOwner { - val owner = createOwner(symbol) - require(symbol.isBound) - require(symbol.owner === owner) { - "Attempt to rebind an IR symbol or to re-create its owner: old owner ${symbol.owner.render()}, new owner ${owner.render()}" - } - return owner - } - } - - private open inner class FlatSymbolTable : SymbolTableBase(lock) - where Descriptor : DeclarationDescriptor, - SymbolOwner : IrSymbolOwner, - Symbol : IrBindableSymbol { - val descriptorToSymbol = hashMapOf() - val idSignatureToSymbol = hashMapOf() - - override fun signature(descriptor: Descriptor): IdSignature? = - signaturer.composeSignature(descriptor) - - override fun get(descriptor: Descriptor, signature: IdSignature?): Symbol? = - if (signature != null) { - idSignatureToSymbol[signature] - } else { - descriptorToSymbol[descriptor] - } - - @OptIn(ObsoleteDescriptorBasedAPI::class) - override fun set(symbol: Symbol) { - val signature = symbol.signature - if (signature != null) { - idSignatureToSymbol[signature] = symbol - } else if (symbol.hasDescriptor) { - descriptorToSymbol[symbol.descriptor] = symbol - } - } - - override fun get(signature: IdSignature): Symbol? = idSignatureToSymbol[signature] - - override fun set(signature: IdSignature, symbol: Symbol) { - idSignatureToSymbol[signature] = symbol - } - } - - private inner class EnumEntrySymbolTable : FlatSymbolTable() { - override fun signature(descriptor: ClassDescriptor): IdSignature? = signaturer.composeEnumEntrySignature(descriptor) - } - - private inner class FieldSymbolTable : FlatSymbolTable() { - override fun signature(descriptor: PropertyDescriptor): IdSignature? = signaturer.composeFieldSignature(descriptor) - } - - private inner class ScopedSymbolTable : SymbolTableBase(lock) - where Descriptor : DeclarationDescriptor, - SymbolOwner : IrSymbolOwner, - Symbol : IrBindableSymbol { - inner class Scope(val owner: IrSymbol, val parent: Scope?) { - private val descriptorToSymbol = hashMapOf() - private val idSignatureToSymbol = hashMapOf() - - private fun getByDescriptor(descriptor: Descriptor): Symbol? = - descriptorToSymbol[descriptor] ?: parent?.getByDescriptor(descriptor) - - private fun getByIdSignature(signature: IdSignature): Symbol? = - idSignatureToSymbol[signature] ?: parent?.getByIdSignature(signature) - - operator fun get(descriptor: Descriptor, signature: IdSignature?): Symbol? = - if (signature != null) { - getByIdSignature(signature) - } else { - getByDescriptor(descriptor) - } - - fun getLocal(descriptor: Descriptor) = descriptorToSymbol[descriptor] - - @OptIn(ObsoleteDescriptorBasedAPI::class) - operator fun set(descriptor: Descriptor, symbol: Symbol) { - symbol.signature?.let { - require(descriptor is TypeParameterDescriptor) - idSignatureToSymbol[it] = symbol - } ?: run { - assert(symbol.hasDescriptor) - descriptorToSymbol[symbol.descriptor] = symbol - } - } - - operator fun get(signature: IdSignature): Symbol? = - idSignatureToSymbol[signature] ?: parent?.get(signature) - - operator fun set(signature: IdSignature, symbol: Symbol) { - idSignatureToSymbol[signature] = symbol - } - - fun dumpTo(stringBuilder: StringBuilder): StringBuilder = - stringBuilder.also { - it.append("owner=") - it.append(owner) - it.append("; ") - descriptorToSymbol.keys.joinTo(prefix = "[", postfix = "]", buffer = it) - it.append('\n') - parent?.dumpTo(it) - } - - fun dump(): String = dumpTo(StringBuilder()).toString() - } - - private var currentScope: Scope? = null - - override fun signature(descriptor: Descriptor): IdSignature? = - signaturer.composeSignature(descriptor) - - override fun get(descriptor: Descriptor, signature: IdSignature?): Symbol? { - val scope = currentScope ?: return null - return scope[descriptor, signature] - } - - @OptIn(ObsoleteDescriptorBasedAPI::class) - override fun set(symbol: Symbol) { - val scope = currentScope ?: throw AssertionError("No active scope") - scope[symbol.descriptor] = symbol - } - - override fun get(signature: IdSignature): Symbol? { - val scope = currentScope ?: return null - return scope[signature] - } - - override fun set(signature: IdSignature, symbol: Symbol) { - val scope = currentScope ?: throw AssertionError("No active scope") - scope[signature] = symbol - } - - inline fun declareLocal(descriptor: Descriptor, createSymbol: () -> Symbol, createOwner: (Symbol) -> SymbolOwner): SymbolOwner { - val scope = currentScope ?: throw AssertionError("No active scope") - val symbol = scope.getLocal(descriptor) ?: createSymbol().also { scope[descriptor] = it } - return createOwnerSafe(symbol, createOwner) - } - - fun introduceLocal(descriptor: Descriptor, symbol: Symbol) { - val scope = currentScope ?: throw AssertionError("No active scope") - scope[descriptor, signature(descriptor)]?.let { - throw AssertionError("$descriptor is already bound to $it") - } - scope[descriptor] = symbol - } - - fun enterScope(owner: IrSymbol) { - currentScope = Scope(owner, currentScope) - } - - fun leaveScope(owner: IrSymbol) { - currentScope?.owner.let { - assert(it == owner) { "Unexpected leaveScope: owner=$owner, currentScope.owner=$it" } - } - - currentScope = currentScope?.parent - - if (currentScope != null && unboundSymbols.isNotEmpty()) { - @OptIn(ObsoleteDescriptorBasedAPI::class) - throw AssertionError("Local scope contains unbound symbols: ${unboundSymbols.joinToString { it.descriptor.toString() }}") - } - } - - fun dump(): String = - currentScope?.dump() ?: "" - } - - private val externalPackageFragmentTable = - FlatSymbolTable() - private val scriptSymbolTable = FlatSymbolTable() - private val classSymbolTable = FlatSymbolTable() - private val constructorSymbolTable = FlatSymbolTable() - private val enumEntrySymbolTable = EnumEntrySymbolTable() - private val fieldSymbolTable = FieldSymbolTable() - private val simpleFunctionSymbolTable = FlatSymbolTable() - private val propertySymbolTable = FlatSymbolTable() - private val typeAliasSymbolTable = FlatSymbolTable() - - private val globalTypeParameterSymbolTable = FlatSymbolTable() - private val scopedTypeParameterSymbolTable by threadLocal { - ScopedSymbolTable() - } - private val valueParameterSymbolTable by threadLocal { - ScopedSymbolTable() - } - private val variableSymbolTable by threadLocal { - ScopedSymbolTable() - } - private val localDelegatedPropertySymbolTable by threadLocal { - ScopedSymbolTable() - } - private val scopedSymbolTables by threadLocal { - listOf(valueParameterSymbolTable, variableSymbolTable, scopedTypeParameterSymbolTable, localDelegatedPropertySymbolTable) - } - - @ObsoleteDescriptorBasedAPI - fun referenceExternalPackageFragment(descriptor: PackageFragmentDescriptor) = - externalPackageFragmentTable.referenced(descriptor) { IrExternalPackageFragmentSymbolImpl(descriptor) } - - @ObsoleteDescriptorBasedAPI - fun declareExternalPackageFragment(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment { - return externalPackageFragmentTable.declare( - descriptor, - { IrExternalPackageFragmentSymbolImpl(descriptor) }, - { IrExternalPackageFragmentImpl(it, descriptor.fqName) } - ) - } - - @ObsoleteDescriptorBasedAPI - fun declareExternalPackageFragmentIfNotExists(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment { - return externalPackageFragmentTable.declareIfNotExists( - descriptor, - { IrExternalPackageFragmentSymbolImpl(descriptor) }, - { IrExternalPackageFragmentImpl(it, descriptor.fqName) } - ) - } - - @ObsoleteDescriptorBasedAPI - fun declareAnonymousInitializer( - startOffset: Int, - endOffset: Int, - origin: IrDeclarationOrigin, - descriptor: ClassDescriptor - ): IrAnonymousInitializer = - irFactory.createAnonymousInitializer( - startOffset, endOffset, origin, - IrAnonymousInitializerSymbolImpl(descriptor) - ) - - @ObsoleteDescriptorBasedAPI - fun declareScript( - startOffset: Int, - endOffset: Int, - descriptor: ScriptDescriptor, - scriptFactory: (IrScriptSymbol) -> IrScript = { symbol: IrScriptSymbol -> - IrScriptImpl(symbol, nameProvider.nameForDeclaration(descriptor), irFactory, startOffset, endOffset) - } - ): IrScript { - return scriptSymbolTable.declare( - descriptor, - { IrScriptSymbolImpl(descriptor) }, - scriptFactory - ) - } + // ------------------------------------ script ------------------------------------ fun declareScript( signature: IdSignature, symbolFactory: () -> IrScriptSymbol, - scriptFactory: (IrScriptSymbol) -> IrScript + scriptFactory: (IrScriptSymbol) -> IrScript, ): IrScript { - return scriptSymbolTable.declare( + return scriptSlice.declare( signature, symbolFactory, scriptFactory ) } - @ObsoleteDescriptorBasedAPI - override fun referenceScript(descriptor: ScriptDescriptor): IrScriptSymbol = - scriptSymbolTable.referenced(descriptor) { IrScriptSymbolImpl(descriptor) } - - private fun createClassSymbol(descriptor: ClassDescriptor, signature: IdSignature?): IrClassSymbol = - signature?.let { IrClassPublicSymbolImpl(it, descriptor) } ?: IrClassSymbolImpl(descriptor) - - @ObsoleteDescriptorBasedAPI - fun declareClass( - descriptor: ClassDescriptor, - classFactory: (IrClassSymbol) -> IrClass - ): IrClass { - return classSymbolTable.declare( - descriptor, - { createClassSymbol(descriptor, signaturer.composeSignature(descriptor)) }, - classFactory - ) - } + // ------------------------------------ class ------------------------------------ fun declareClass( signature: IdSignature, symbolFactory: () -> IrClassSymbol, - classFactory: (IrClassSymbol) -> IrClass + classFactory: (IrClassSymbol) -> IrClass, ): IrClass { - return classSymbolTable.declare( + return classSlice.declare( signature, symbolFactory, classFactory @@ -517,187 +70,549 @@ open class SymbolTable( } fun declareClassWithSignature(signature: IdSignature, symbol: IrClassSymbol) { - classSymbolTable.set(signature, symbol) + classSlice.set(signature, symbol) } - @ObsoleteDescriptorBasedAPI - fun declareClassIfNotExists(descriptor: ClassDescriptor, classFactory: (IrClassSymbol) -> IrClass): IrClass = - classSymbolTable.declareIfNotExists(descriptor, { signature -> createClassSymbol(descriptor, signature) }, classFactory) - - // Note: used in native - @ObsoleteDescriptorBasedAPI - @Suppress("unused") - fun declareClassFromLinker(descriptor: ClassDescriptor, signature: IdSignature, factory: (IrClassSymbol) -> IrClass): IrClass { - return classSymbolTable.run { - if (signature.isPubliclyVisible) { - declare(signature, descriptor, { IrClassPublicSymbolImpl(signature, descriptor) }, factory) - } else { - declare(descriptor, { IrClassSymbolImpl(descriptor) }, factory) - } - } + fun declareClassIfNotExists( + signature: IdSignature, + symbolFactory: () -> IrClassSymbol, + classFactory: (IrClassSymbol) -> IrClass, + ): IrClass { + return classSlice.declareIfNotExists(signature, symbolFactory, classFactory) } - @ObsoleteDescriptorBasedAPI - override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol = - @Suppress("Reformat") - // This is needed for cases like kt46069.kt, where psi2ir creates descriptor-less IR elements for adapted function references. - // In JVM IR, symbols are linked via descriptors by default, so for an adapted function reference, an IrBasedClassDescriptor - // is created for any classifier used in the function parameter/return types. Any attempt to translate such type to IrType goes - // to this method, which puts the descriptor into unboundClasses, which causes an assertion failure later because we won't bind - // such symbol anywhere. - // TODO: maybe there's a better solution. - if (descriptor is IrBasedClassDescriptor) - descriptor.owner.symbol - else - classSymbolTable.referenced(descriptor) { signature -> createClassSymbol(descriptor, signature) } - fun referenceClass( signature: IdSignature, symbolFactory: () -> IrClassSymbol, - classFactory: (IrClassSymbol) -> IrClass - ) = - classSymbolTable.referenced(signature) { declareClass(signature, symbolFactory, classFactory).symbol } + classFactory: (IrClassSymbol) -> IrClass, + ): IrClassSymbol { + return classSlice.referenced(signature) { declareClass(signature, symbolFactory, classFactory).symbol } + } - override fun referenceClass(signature: IdSignature): IrClassSymbol = - classSymbolTable.run { - if (signature.isPubliclyVisible) referenced(signature) { IrClassPublicSymbolImpl(signature) } - else IrClassSymbolImpl().also { - it.privateSignature = signature - } - } - - val unboundClasses: Set get() = classSymbolTable.unboundSymbols - - private fun createConstructorSymbol(descriptor: ClassConstructorDescriptor, signature: IdSignature?): IrConstructorSymbol = - signature?.let { IrConstructorPublicSymbolImpl(it, descriptor) } ?: IrConstructorSymbolImpl(descriptor) - - @ObsoleteDescriptorBasedAPI - fun declareConstructor( - descriptor: ClassConstructorDescriptor, - constructorFactory: (IrConstructorSymbol) -> IrConstructor - ): IrConstructor = - constructorSymbolTable.declare( - descriptor, - { signature -> createConstructorSymbol(descriptor, signature) }, - constructorFactory + override fun referenceClass(signature: IdSignature): IrClassSymbol { + return referenceClassImpl( + signature, + { IrClassPublicSymbolImpl(signature) }, + { IrClassSymbolImpl().also { it.privateSignature = signature } } ) + } + + // TODO: add OptIn + internal inline fun referenceClassImpl( + signature: IdSignature, + publicSymbolFactory: () -> IrClassSymbol, + privateSymbolFactory: () -> IrClassSymbol, + ): IrClassSymbol { + return when { + signature.isPubliclyVisible -> classSlice.referenced(signature) { publicSymbolFactory() } + else -> privateSymbolFactory() + } + } + + // ------------------------------------ constructor ------------------------------------ fun declareConstructor( signature: IdSignature, symbolFactory: () -> IrConstructorSymbol, - constructorFactory: (IrConstructorSymbol) -> IrConstructor + constructorFactory: (IrConstructorSymbol) -> IrConstructor, ): IrConstructor { - return constructorSymbolTable.declare( + return constructorSlice.declare( signature, symbolFactory, constructorFactory ) } - @ObsoleteDescriptorBasedAPI fun declareConstructorIfNotExists( - descriptor: ClassConstructorDescriptor, + signature: IdSignature, + symbolFactory: () -> IrConstructorSymbol, constructorFactory: (IrConstructorSymbol) -> IrConstructor, - ): IrConstructor = - constructorSymbolTable.declareIfNotExists( - descriptor, - { signature -> createConstructorSymbol(descriptor, signature) }, - constructorFactory - ) - - fun declareConstructorWithSignature(signature: IdSignature, symbol: IrConstructorSymbol) { - constructorSymbolTable.set(signature, symbol) + ): IrConstructor { + return constructorSlice.declareIfNotExists(signature, symbolFactory, constructorFactory) } - @ObsoleteDescriptorBasedAPI - override fun referenceConstructor(descriptor: ClassConstructorDescriptor): IrConstructorSymbol = - constructorSymbolTable.referenced(descriptor) { signature -> createConstructorSymbol(descriptor, signature) } + fun declareConstructorWithSignature(signature: IdSignature, symbol: IrConstructorSymbol) { + constructorSlice.set(signature, symbol) + } - fun referenceConstructorIfAny(signature: IdSignature): IrConstructorSymbol? = - constructorSymbolTable.get(signature) + fun referenceConstructorIfAny(signature: IdSignature): IrConstructorSymbol? { + return constructorSlice.get(signature) + } - // Note: used in native - @ObsoleteDescriptorBasedAPI - @Suppress("unused") - fun declareConstructorFromLinker( - descriptor: ClassConstructorDescriptor, + override fun referenceConstructor(signature: IdSignature): IrConstructorSymbol { + return referenceConstructorImpl( + signature, + { IrConstructorPublicSymbolImpl(signature) }, + { IrConstructorSymbolImpl() } + ) + } + + // TODO: add OptIn + internal inline fun referenceConstructorImpl( signature: IdSignature, - constructorFactory: (IrConstructorSymbol) -> IrConstructor - ): IrConstructor { - return constructorSymbolTable.run { - if (signature.isPubliclyVisible) { - declare(signature, descriptor, { IrConstructorPublicSymbolImpl(signature, descriptor) }, constructorFactory) - } else { - declare(descriptor, { IrConstructorSymbolImpl(descriptor) }, constructorFactory) + publicSymbolFactory: () -> IrConstructorSymbol, + privateSymbolFactory: () -> IrConstructorSymbol, + ): IrConstructorSymbol { + return when { + signature.isPubliclyVisible -> constructorSlice.referenced(signature) { publicSymbolFactory() } + else -> privateSymbolFactory().also { + it.privateSignature = signature } } } - override fun referenceConstructor(signature: IdSignature): IrConstructorSymbol = - constructorSymbolTable.run { - if (signature.isPubliclyVisible) referenced(signature) { IrConstructorPublicSymbolImpl(signature) } - else IrConstructorSymbolImpl() - } - - val unboundConstructors: Set get() = constructorSymbolTable.unboundSymbols - - private fun createEnumEntrySymbol(descriptor: ClassDescriptor, signature: IdSignature?): IrEnumEntrySymbol = - signature?.let { IrEnumEntryPublicSymbolImpl(it, descriptor) } ?: IrEnumEntrySymbolImpl(descriptor) - - @ObsoleteDescriptorBasedAPI - fun declareEnumEntry( - startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor, - factory: (IrEnumEntrySymbol) -> IrEnumEntry = { - irFactory.createEnumEntry(startOffset, endOffset, origin, nameProvider.nameForDeclaration(descriptor), it) - } - ): IrEnumEntry = - enumEntrySymbolTable.declare( - descriptor, - { signature -> createEnumEntrySymbol(descriptor, signature) }, - factory - ) + // ------------------------------------ enum entry ------------------------------------ fun declareEnumEntry( signature: IdSignature, symbolFactory: () -> IrEnumEntrySymbol, - enumEntryFactory: (IrEnumEntrySymbol) -> IrEnumEntry - ): IrEnumEntry = enumEntrySymbolTable.declare(signature, symbolFactory, enumEntryFactory) - - @ObsoleteDescriptorBasedAPI - fun declareEnumEntryIfNotExists(descriptor: ClassDescriptor, factory: (IrEnumEntrySymbol) -> IrEnumEntry): IrEnumEntry = - enumEntrySymbolTable.declareIfNotExists(descriptor, { signature -> createEnumEntrySymbol(descriptor, signature) }, factory) - - // Note: used in native - @ObsoleteDescriptorBasedAPI - @Suppress("unused") - fun declareEnumEntryFromLinker( - descriptor: ClassDescriptor, - signature: IdSignature, - factory: (IrEnumEntrySymbol) -> IrEnumEntry + enumEntryFactory: (IrEnumEntrySymbol) -> IrEnumEntry, ): IrEnumEntry { - return enumEntrySymbolTable.run { - if (signature.isPubliclyVisible) { - declare(signature, descriptor, { IrEnumEntryPublicSymbolImpl(signature, descriptor) }, factory) - } else { - declare(descriptor, { IrEnumEntrySymbolImpl(descriptor) }, factory) + return enumEntrySlice.declare(signature, symbolFactory, enumEntryFactory) + } + + fun declareEnumEntryIfNotExists( + signature: IdSignature, + symbolFactory: () -> IrEnumEntrySymbol, + classFactory: (IrEnumEntrySymbol) -> IrEnumEntry, + ): IrEnumEntry { + return enumEntrySlice.declareIfNotExists(signature, symbolFactory, classFactory) + } + + override fun referenceEnumEntry(signature: IdSignature): IrEnumEntrySymbol { + return referenceEnumEntryImpl( + signature, + { IrEnumEntryPublicSymbolImpl(signature) }, + { IrEnumEntrySymbolImpl() } + ) + } + + // TODO: add OptIn + internal inline fun referenceEnumEntryImpl( + signature: IdSignature, + publicSymbolFactory: () -> IrEnumEntrySymbol, + privateSymbolFactory: () -> IrEnumEntrySymbol, + ): IrEnumEntrySymbol { + return when { + signature.isPubliclyVisible -> enumEntrySlice.referenced(signature) { publicSymbolFactory() } + else -> privateSymbolFactory().also { + it.privateSignature = signature } } } - @ObsoleteDescriptorBasedAPI - override fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol = - enumEntrySymbolTable.referenced(descriptor) { signature -> createEnumEntrySymbol(descriptor, signature) } + // ------------------------------------ field ------------------------------------ - override fun referenceEnumEntry(signature: IdSignature) = - enumEntrySymbolTable.run { - if (signature.isPubliclyVisible) referenced(signature) { IrEnumEntryPublicSymbolImpl(signature) } - else IrEnumEntrySymbolImpl() + fun declareField( + signature: IdSignature, + symbolFactory: () -> IrFieldSymbol, + propertyFactory: (IrFieldSymbol) -> IrField, + ): IrField { + return fieldSlice.declare( + signature, + symbolFactory, + propertyFactory + ) + } + + fun declareFieldWithSignature(signature: IdSignature, symbol: IrFieldSymbol) { + fieldSlice.set(signature, symbol) + } + + override fun referenceField(signature: IdSignature): IrFieldSymbol { + return referenceFieldImpl( + signature, + { IrFieldPublicSymbolImpl(signature) }, + { IrFieldSymbolImpl() } + ) + } + + // TODO: add OptIn + internal inline fun referenceFieldImpl( + signature: IdSignature, + publicSymbolFactory: () -> IrFieldSymbol, + privateSymbolFactory: () -> IrFieldSymbol, + ): IrFieldSymbol { + return when { + signature.isPubliclyVisible -> fieldSlice.referenced(signature) { publicSymbolFactory() } + else -> privateSymbolFactory().also { + it.privateSignature = signature + } + } + } + + // ------------------------------------ property ------------------------------------ + + fun declareProperty( + signature: IdSignature, + symbolFactory: () -> IrPropertySymbol, + propertyFactory: (IrPropertySymbol) -> IrProperty, + ): IrProperty { + return propertySlice.declare( + signature, + symbolFactory, + propertyFactory + ) + } + + fun declarePropertyIfNotExists( + signature: IdSignature, + symbolFactory: () -> IrPropertySymbol, + propertyFactory: (IrPropertySymbol) -> IrProperty, + ): IrProperty { + return propertySlice.declareIfNotExists(signature, symbolFactory, propertyFactory) + } + + fun declarePropertyWithSignature(signature: IdSignature, symbol: IrPropertySymbol) { + propertySlice.set(signature, symbol) + } + + fun referencePropertyIfAny(signature: IdSignature): IrPropertySymbol? { + return propertySlice.get(signature) + } + + override fun referenceProperty(signature: IdSignature): IrPropertySymbol { + return referencePropertyImpl( + signature, + { IrPropertyPublicSymbolImpl(signature) }, + { IrPropertySymbolImpl() } + ) + } + + // TODO: add OptIn + internal inline fun referencePropertyImpl( + signature: IdSignature, + publicSymbolFactory: () -> IrPropertySymbol, + privateSymbolFactory: () -> IrPropertySymbol, + ): IrPropertySymbol { + return when { + signature.isPubliclyVisible -> propertySlice.referenced(signature) { publicSymbolFactory() } + else -> privateSymbolFactory().also { + it.privateSignature = signature + } + } + } + + // ------------------------------------ typealias ------------------------------------ + + fun declareTypeAlias( + signature: IdSignature, + symbolFactory: () -> IrTypeAliasSymbol, + factory: (IrTypeAliasSymbol) -> IrTypeAlias, + ): IrTypeAlias { + return typeAliasSlice.declare(signature, symbolFactory, factory) + } + + fun declareTypeAliasIfNotExists( + signature: IdSignature, + symbolFactory: () -> IrTypeAliasSymbol, + typeAliasFactory: (IrTypeAliasSymbol) -> IrTypeAlias, + ): IrTypeAlias { + return typeAliasSlice.declareIfNotExists(signature, symbolFactory, typeAliasFactory) + } + + override fun referenceTypeAlias(signature: IdSignature): IrTypeAliasSymbol { + return referenceTypeAliasImpl( + signature, + { IrTypeAliasPublicSymbolImpl(signature) }, + { IrTypeAliasSymbolImpl() } + ) + } + + // TODO: add OptIn + internal inline fun referenceTypeAliasImpl( + signature: IdSignature, + publicSymbolFactory: () -> IrTypeAliasSymbol, + privateSymbolFactory: () -> IrTypeAliasSymbol, + ): IrTypeAliasSymbol { + return when { + signature.isPubliclyVisible -> typeAliasSlice.referenced(signature) { publicSymbolFactory() } + else -> privateSymbolFactory().also { + it.privateSignature = signature + } + } + } + + // ------------------------------------ function ------------------------------------ + + fun declareSimpleFunction( + signature: IdSignature, + symbolFactory: () -> IrSimpleFunctionSymbol, + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction, + ): IrSimpleFunction { + return functionSlice.declare( + signature, + symbolFactory, + functionFactory + ) + } + + fun declareSimpleFunctionIfNotExists( + signature: IdSignature, + symbolFactory: () -> IrSimpleFunctionSymbol, + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction, + ): IrSimpleFunction { + return functionSlice.declareIfNotExists(signature, symbolFactory, functionFactory) + } + + fun declareSimpleFunctionWithSignature(signature: IdSignature, symbol: IrSimpleFunctionSymbol) { + functionSlice.set(signature, symbol) + } + + fun referenceSimpleFunctionIfAny(signature: IdSignature): IrSimpleFunctionSymbol? = + functionSlice.get(signature) + + override fun referenceSimpleFunction(signature: IdSignature): IrSimpleFunctionSymbol { + return referenceSimpleFunctionImpl( + signature, + { IrSimpleFunctionPublicSymbolImpl(signature) }, + { IrSimpleFunctionSymbolImpl().also { it.privateSignature = signature } } + ) + } + + // TODO: add OptIn + internal inline fun referenceSimpleFunctionImpl( + signature: IdSignature, + publicSymbolFactory: () -> IrSimpleFunctionSymbol, + privateSymbolFactory: () -> IrSimpleFunctionSymbol, + ): IrSimpleFunctionSymbol { + return when { + signature.isPubliclyVisible -> functionSlice.referenced(signature) { publicSymbolFactory() } + else -> privateSymbolFactory().also { + it.privateSignature = signature + } + } + } + + // ------------------------------------ type parameter ------------------------------------ + + fun declareGlobalTypeParameter( + signature: IdSignature, + symbolFactory: () -> IrTypeParameterSymbol, + typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter, + ): IrTypeParameter { + return globalTypeParameterSlice.declare(signature, symbolFactory, typeParameterFactory) + } + + fun declareScopedTypeParameter( + signature: IdSignature, + symbolFactory: (IdSignature) -> IrTypeParameterSymbol, + typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter, + ): IrTypeParameter { + // TODO: suspicios + return typeParameterFactory(symbolFactory(signature)) + } + + override fun referenceTypeParameter(signature: IdSignature): IrTypeParameterSymbol { + return referenceTypeParameterImpl( + signature, + { IrTypeParameterPublicSymbolImpl(signature) }, + { IrTypeParameterSymbolImpl() } + ) + } + + // TODO: add OptIn + internal inline fun referenceTypeParameterImpl( + signature: IdSignature, + publicSymbolFactory: () -> IrTypeParameterSymbol, + privateSymbolFactory: () -> IrTypeParameterSymbol, + ): IrTypeParameterSymbol { + return when { + signature.isPubliclyVisible -> globalTypeParameterSlice.referenced(signature) { publicSymbolFactory() } + else -> privateSymbolFactory().also { + it.privateSignature = signature + } + } + } + + // ------------------------------------ scopes ------------------------------------ + + // TODO: move to extensions + @OptIn(ObsoleteDescriptorBasedAPI::class) + override fun enterScope(symbol: IrSymbol) { + descriptorExtension.enterScope(symbol) + } + + // TODO: move to extensions + @OptIn(ObsoleteDescriptorBasedAPI::class) + override fun enterScope(owner: IrDeclaration) { + descriptorExtension.enterScope(owner) + } + + // TODO: move to extensions + @OptIn(ObsoleteDescriptorBasedAPI::class) + override fun leaveScope(symbol: IrSymbol) { + descriptorExtension.leaveScope(symbol) + } + + // TODO: move to extensions + @OptIn(ObsoleteDescriptorBasedAPI::class) + override fun leaveScope(owner: IrDeclaration) { + descriptorExtension.leaveScope(owner) + } + + // ------------------------------------ utils ------------------------------------ + + /** + * This function is quite messy and doesn't have good contract of what exactly is traversed. + * Basic idea is it traverse symbols which can be reasonable referered from other module + * + * Be careful when using it, and avoid it, except really need. + * + * TODO: add some OptIn + */ + fun forEachDeclarationSymbol(block: (IrSymbol) -> Unit) { + classSlice.forEachSymbol { block(it) } + constructorSlice.forEachSymbol { block(it) } + functionSlice.forEachSymbol { block(it) } + propertySlice.forEachSymbol { block(it) } + enumEntrySlice.forEachSymbol { block(it) } + typeAliasSlice.forEachSymbol { block(it) } + fieldSlice.forEachSymbol { block(it) } + } + + val allUnboundSymbols: Set + get() = buildSet { + fun addUnbound(slice: SymbolTableSlice) { + slice.unboundSymbols.filterTo(this) { !it.isBound } + } + + addUnbound(classSlice) + addUnbound(constructorSlice) + addUnbound(functionSlice) + addUnbound(propertySlice) + addUnbound(enumEntrySlice) + addUnbound(typeAliasSlice) + addUnbound(fieldSlice) } - val unboundEnumEntries: Set get() = enumEntrySymbolTable.unboundSymbols + // ------------------------------------ descriptors ------------------------------------ - private fun createFieldSymbol(descriptor: PropertyDescriptor, signature: IdSignature?): IrFieldSymbol = - signature?.let { IrFieldPublicSymbolImpl(it, descriptor) } ?: IrFieldSymbolImpl(descriptor) + @ObsoleteDescriptorBasedAPI + override fun referenceScript(descriptor: ScriptDescriptor): IrScriptSymbol { + return descriptorExtension.referenceScript(descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun declareScript( + startOffset: Int, + endOffset: Int, + descriptor: ScriptDescriptor, + ): IrScript { + return descriptorExtension.declareScript(startOffset, endOffset, descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun referenceExternalPackageFragment(descriptor: PackageFragmentDescriptor): IrExternalPackageFragmentSymbol { + return descriptorExtension.referenceExternalPackageFragment(descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun declareExternalPackageFragment(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment { + return descriptorExtension.declareExternalPackageFragment(descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun declareExternalPackageFragmentIfNotExists(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment { + return descriptorExtension.declareExternalPackageFragmentIfNotExists(descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun declareAnonymousInitializer( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: ClassDescriptor, + ): IrAnonymousInitializer { + return descriptorExtension.declareAnonymousInitializer(startOffset, endOffset, origin, descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun declareClass( + descriptor: ClassDescriptor, + classFactory: (IrClassSymbol) -> IrClass, + ): IrClass { + return descriptorExtension.declareClass(descriptor, classFactory) + } + + @ObsoleteDescriptorBasedAPI + fun declareClassIfNotExists(descriptor: ClassDescriptor, classFactory: (IrClassSymbol) -> IrClass): IrClass { + return descriptorExtension.declareClassIfNotExists(descriptor, classFactory) + } + + @ObsoleteDescriptorBasedAPI + fun declareClassFromLinker(descriptor: ClassDescriptor, signature: IdSignature, factory: (IrClassSymbol) -> IrClass): IrClass { + return descriptorExtension.declareClassFromLinker(descriptor, signature, factory) + } + + @ObsoleteDescriptorBasedAPI + override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol { + return descriptorExtension.referenceClass(descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun declareConstructor( + descriptor: ClassConstructorDescriptor, + constructorFactory: (IrConstructorSymbol) -> IrConstructor, + ): IrConstructor { + return descriptorExtension.declareConstructor(descriptor, constructorFactory) + } + + @ObsoleteDescriptorBasedAPI + fun declareConstructorIfNotExists( + descriptor: ClassConstructorDescriptor, + constructorFactory: (IrConstructorSymbol) -> IrConstructor, + ): IrConstructor { + return descriptorExtension.declareConstructorIfNotExists(descriptor, constructorFactory) + } + + @ObsoleteDescriptorBasedAPI + override fun referenceConstructor(descriptor: ClassConstructorDescriptor): IrConstructorSymbol { + return descriptorExtension.referenceConstructor(descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun declareConstructorFromLinker( + descriptor: ClassConstructorDescriptor, + signature: IdSignature, + constructorFactory: (IrConstructorSymbol) -> IrConstructor, + ): IrConstructor { + return descriptorExtension.declareConstructorFromLinker(descriptor, signature, constructorFactory) + } + + @ObsoleteDescriptorBasedAPI + fun declareEnumEntry( + startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor, + ): IrEnumEntry { + return descriptorExtension.declareEnumEntry(startOffset, endOffset, origin, descriptor) + } + + @ObsoleteDescriptorBasedAPI + fun declareEnumEntry( + descriptor: ClassDescriptor, + factory: (IrEnumEntrySymbol) -> IrEnumEntry, + ): IrEnumEntry { + return descriptorExtension.declareEnumEntry(descriptor, factory) + } + + @ObsoleteDescriptorBasedAPI + fun declareEnumEntryIfNotExists(descriptor: ClassDescriptor, factory: (IrEnumEntrySymbol) -> IrEnumEntry): IrEnumEntry { + return descriptorExtension.declareEnumEntryIfNotExists(descriptor, factory) + } + + @ObsoleteDescriptorBasedAPI + fun declareEnumEntryFromLinker( + descriptor: ClassDescriptor, + signature: IdSignature, + factory: (IrEnumEntrySymbol) -> IrEnumEntry, + ): IrEnumEntry { + return descriptorExtension.declareEnumEntryFromLinker(descriptor, signature, factory) + } + + @ObsoleteDescriptorBasedAPI + override fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol { + return descriptorExtension.referenceEnumEntry(descriptor) + } @OptIn(ObsoleteDescriptorBasedAPI::class) fun declareField( @@ -707,28 +622,10 @@ open class SymbolTable( descriptor: PropertyDescriptor, type: IrType, visibility: DescriptorVisibility? = null, - fieldFactory: (IrFieldSymbol) -> IrField = { - irFactory.createField( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = nameProvider.nameForDeclaration(descriptor), - visibility = visibility ?: it.descriptor.visibility, - symbol = it, - type = type, - isFinal = !it.descriptor.isVar, - isStatic = it.descriptor.dispatchReceiverParameter == null, - isExternal = it.descriptor.isEffectivelyExternal(), - ).apply { - metadata = DescriptorMetadataSource.Property(it.descriptor) - } - } - ): IrField = - fieldSymbolTable.declare( - descriptor, - { signature -> createFieldSymbol(descriptor, signature) }, - fieldFactory - ) + fieldFactory: (IrFieldSymbol) -> IrField, + ): IrField { + return descriptorExtension.declareField(startOffset, endOffset, origin, descriptor, type, visibility, fieldFactory) + } @ObsoleteDescriptorBasedAPI fun declareField( @@ -737,43 +634,15 @@ open class SymbolTable( origin: IrDeclarationOrigin, descriptor: PropertyDescriptor, type: IrType, - irInitializer: IrExpressionBody? - ): IrField = - declareField(startOffset, endOffset, origin, descriptor, type).apply { - initializer = irInitializer - } - - fun declareField( - signature: IdSignature, - symbolFactory: () -> IrFieldSymbol, - propertyFactory: (IrFieldSymbol) -> IrField + irInitializer: IrExpressionBody?, ): IrField { - return fieldSymbolTable.declare( - signature, - symbolFactory, - propertyFactory - ) - } - - fun declareFieldWithSignature(signature: IdSignature, symbol: IrFieldSymbol) { - fieldSymbolTable.set(signature, symbol) + return descriptorExtension.declareField(startOffset, endOffset, origin, descriptor, type, irInitializer) } @ObsoleteDescriptorBasedAPI - override fun referenceField(descriptor: PropertyDescriptor): IrFieldSymbol = - fieldSymbolTable.referenced(descriptor) { signature -> createFieldSymbol(descriptor, signature) } - - override fun referenceField(signature: IdSignature): IrFieldSymbol = - fieldSymbolTable.run { - if (signature.isPubliclyVisible) { - referenced(signature) { IrFieldPublicSymbolImpl(signature) } - } else IrFieldSymbolImpl() - } - - val unboundFields: Set get() = fieldSymbolTable.unboundSymbols - - private fun createPropertySymbol(descriptor: PropertyDescriptor, signature: IdSignature?): IrPropertySymbol = - signature?.let { IrPropertyPublicSymbolImpl(it, descriptor) } ?: IrPropertySymbolImpl(descriptor) + override fun referenceField(descriptor: PropertyDescriptor): IrFieldSymbol { + return descriptorExtension.referenceField(descriptor) + } @ObsoleteDescriptorBasedAPI fun declareProperty( @@ -782,48 +651,22 @@ open class SymbolTable( origin: IrDeclarationOrigin, descriptor: PropertyDescriptor, isDelegated: Boolean = descriptor.isDelegated, - propertyFactory: (IrPropertySymbol) -> IrProperty = { symbol -> - irFactory.createProperty( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = nameProvider.nameForDeclaration(descriptor), - visibility = descriptor.visibility, - modality = descriptor.modality, - symbol = symbol, - isVar = descriptor.isVar, - isConst = descriptor.isConst, - isLateinit = descriptor.isLateInit, - isDelegated = isDelegated, - isExternal = descriptor.isEffectivelyExternal(), - isExpect = descriptor.isExpect, - isFakeOverride = descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE, - ).apply { - metadata = DescriptorMetadataSource.Property(symbol.descriptor) - } - } - ): IrProperty = - propertySymbolTable.declare( - descriptor, - { signature -> createPropertySymbol(descriptor, signature) }, - propertyFactory - ) - - fun declareProperty( - signature: IdSignature, - symbolFactory: () -> IrPropertySymbol, - propertyFactory: (IrPropertySymbol) -> IrProperty ): IrProperty { - return propertySymbolTable.declare( - signature, - symbolFactory, - propertyFactory - ) + return descriptorExtension.declareProperty(startOffset, endOffset, origin, descriptor, isDelegated) } @ObsoleteDescriptorBasedAPI - fun declarePropertyIfNotExists(descriptor: PropertyDescriptor, propertyFactory: (IrPropertySymbol) -> IrProperty): IrProperty = - propertySymbolTable.declareIfNotExists(descriptor, { signature -> createPropertySymbol(descriptor, signature) }, propertyFactory) + fun declareProperty( + descriptor: PropertyDescriptor, + propertyFactory: (IrPropertySymbol) -> IrProperty, + ): IrProperty { + return descriptorExtension.declareProperty(descriptor, propertyFactory) + } + + @ObsoleteDescriptorBasedAPI + fun declarePropertyIfNotExists(descriptor: PropertyDescriptor, propertyFactory: (IrPropertySymbol) -> IrProperty): IrProperty { + return descriptorExtension.declarePropertyIfNotExists(descriptor, propertyFactory) + } @ObsoleteDescriptorBasedAPI fun declarePropertyFromLinker( @@ -831,144 +674,63 @@ open class SymbolTable( signature: IdSignature, factory: (IrPropertySymbol) -> IrProperty, ): IrProperty { - return propertySymbolTable.run { - if (signature.isPubliclyVisible) { - declare(signature, descriptor, { IrPropertyPublicSymbolImpl(signature, descriptor) }, factory) - } else { - declare(descriptor, { IrPropertySymbolImpl(descriptor) }, factory) - } - } - } - - fun declarePropertyWithSignature(signature: IdSignature, symbol: IrPropertySymbol) { - propertySymbolTable.set(signature, symbol) + return descriptorExtension.declarePropertyFromLinker(descriptor, signature, factory) } @ObsoleteDescriptorBasedAPI - override fun referenceProperty(descriptor: PropertyDescriptor): IrPropertySymbol = - propertySymbolTable.referenced(descriptor) { signature -> createPropertySymbol(descriptor, signature) } - - fun referencePropertyIfAny(signature: IdSignature): IrPropertySymbol? = - propertySymbolTable.get(signature) - - override fun referenceProperty(signature: IdSignature): IrPropertySymbol = - propertySymbolTable.run { - if (signature.isPubliclyVisible) referenced(signature) { IrPropertyPublicSymbolImpl(signature) } - else IrPropertySymbolImpl() - } - - val unboundProperties: Set get() = propertySymbolTable.unboundSymbols - - private fun createTypeAliasSymbol(descriptor: TypeAliasDescriptor, signature: IdSignature?): IrTypeAliasSymbol = - signature?.let { IrTypeAliasPublicSymbolImpl(it, descriptor) } ?: IrTypeAliasSymbolImpl(descriptor) - - @ObsoleteDescriptorBasedAPI - override fun referenceTypeAlias(descriptor: TypeAliasDescriptor): IrTypeAliasSymbol = - typeAliasSymbolTable.referenced(descriptor) { signature -> createTypeAliasSymbol(descriptor, signature) } - - override fun referenceTypeAlias(signature: IdSignature) = - typeAliasSymbolTable.run { - if (signature.isPubliclyVisible) referenced(signature) { IrTypeAliasPublicSymbolImpl(signature) } - else IrTypeAliasSymbolImpl() - } - - @ObsoleteDescriptorBasedAPI - fun declareTypeAlias(descriptor: TypeAliasDescriptor, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias = - typeAliasSymbolTable.declare(descriptor, { signature -> createTypeAliasSymbol(descriptor, signature) }, factory) - - fun declareTypeAlias( - signature: IdSignature, - symbolFactory: () -> IrTypeAliasSymbol, - factory: (IrTypeAliasSymbol) -> IrTypeAlias - ): IrTypeAlias { - return typeAliasSymbolTable.declare(signature, symbolFactory, factory) + override fun referenceProperty(descriptor: PropertyDescriptor): IrPropertySymbol { + return descriptorExtension.referenceProperty(descriptor) } @ObsoleteDescriptorBasedAPI - fun declareTypeAliasIfNotExists(descriptor: TypeAliasDescriptor, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias = - typeAliasSymbolTable.declareIfNotExists(descriptor, { signature -> createTypeAliasSymbol(descriptor, signature) }, factory) + override fun referenceTypeAlias(descriptor: TypeAliasDescriptor): IrTypeAliasSymbol { + return descriptorExtension.referenceTypeAlias(descriptor) + } - val unboundTypeAliases: Set get() = typeAliasSymbolTable.unboundSymbols + @ObsoleteDescriptorBasedAPI + fun declareTypeAlias(descriptor: TypeAliasDescriptor, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias { + return descriptorExtension.declareTypeAlias(descriptor, factory) + } - private fun createSimpleFunctionSymbol(descriptor: FunctionDescriptor, signature: IdSignature?): IrSimpleFunctionSymbol = - signature?.let { IrSimpleFunctionPublicSymbolImpl(it, descriptor) } ?: IrSimpleFunctionSymbolImpl(descriptor) + @ObsoleteDescriptorBasedAPI + fun declareTypeAliasIfNotExists(descriptor: TypeAliasDescriptor, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias { + return descriptorExtension.declareTypeAliasIfNotExists(descriptor, factory) + } @ObsoleteDescriptorBasedAPI fun declareSimpleFunction( descriptor: FunctionDescriptor, - functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction, ): IrSimpleFunction { - return simpleFunctionSymbolTable.declare( - descriptor, - { signature -> createSimpleFunctionSymbol(descriptor, signature) }, - functionFactory - ) - } - - fun declareSimpleFunction( - signature: IdSignature, - symbolFactory: () -> IrSimpleFunctionSymbol, - functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction - ): IrSimpleFunction { - return simpleFunctionSymbolTable.declare( - signature, - symbolFactory, - functionFactory - ) + return descriptorExtension.declareSimpleFunction(descriptor, functionFactory) } @ObsoleteDescriptorBasedAPI fun declareSimpleFunctionIfNotExists( descriptor: FunctionDescriptor, - functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction - ): IrSimpleFunction = - simpleFunctionSymbolTable.declareIfNotExists( - descriptor, { signature -> createSimpleFunctionSymbol(descriptor, signature) }, functionFactory - ) + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction, + ): IrSimpleFunction { + return descriptorExtension.declareSimpleFunctionIfNotExists(descriptor, functionFactory) + } @ObsoleteDescriptorBasedAPI fun declareSimpleFunctionFromLinker( - descriptor: FunctionDescriptor?, + descriptor: FunctionDescriptor, signature: IdSignature, - functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction, ): IrSimpleFunction { - return simpleFunctionSymbolTable.run { - if (signature.isPubliclyVisible) { - declare(signature, descriptor, { IrSimpleFunctionPublicSymbolImpl(signature, descriptor) }, functionFactory) - } else { - declare(descriptor!!, { IrSimpleFunctionSymbolImpl(descriptor) }, functionFactory) - } - } - } - - fun declareSimpleFunctionWithSignature(signature: IdSignature, symbol: IrSimpleFunctionSymbol) { - simpleFunctionSymbolTable.set(signature, symbol) + return descriptorExtension.declareSimpleFunctionFromLinker(descriptor, signature, functionFactory) } @ObsoleteDescriptorBasedAPI - override fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol = - simpleFunctionSymbolTable.referenced(descriptor) { signature -> createSimpleFunctionSymbol(descriptor, signature) } - - fun referenceSimpleFunctionIfAny(signature: IdSignature): IrSimpleFunctionSymbol? = - simpleFunctionSymbolTable.get(signature) - - override fun referenceSimpleFunction(signature: IdSignature): IrSimpleFunctionSymbol { - return simpleFunctionSymbolTable.run { - if (signature.isPubliclyVisible) referenced(signature) { IrSimpleFunctionPublicSymbolImpl(signature) } - else IrSimpleFunctionSymbolImpl().also { - it.privateSignature = signature - } - } + override fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol { + return descriptorExtension.referenceSimpleFunction(descriptor) } @ObsoleteDescriptorBasedAPI - override fun referenceDeclaredFunction(descriptor: FunctionDescriptor) = - simpleFunctionSymbolTable.referenced(descriptor) { throw AssertionError("Function is not declared: $descriptor") } - - val unboundSimpleFunctions: Set get() = simpleFunctionSymbolTable.unboundSymbols - - private fun createTypeParameterSymbol(descriptor: TypeParameterDescriptor, signature: IdSignature?): IrTypeParameterSymbol = - signature?.let { IrTypeParameterPublicSymbolImpl(it, descriptor) } ?: IrTypeParameterSymbolImpl(descriptor) + override fun referenceDeclaredFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol { + return descriptorExtension.referenceDeclaredFunction(descriptor) + } @ObsoleteDescriptorBasedAPI fun declareGlobalTypeParameter( @@ -976,31 +738,8 @@ open class SymbolTable( endOffset: Int, origin: IrDeclarationOrigin, descriptor: TypeParameterDescriptor, - typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter = { - irFactory.createTypeParameter( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = nameProvider.nameForDeclaration(descriptor), - symbol = it, - variance = it.descriptor.variance, - index = it.descriptor.index, - isReified = it.descriptor.isReified - ) - } - ): IrTypeParameter = - globalTypeParameterSymbolTable.declare( - descriptor, - { signature -> createTypeParameterSymbol(descriptor, signature) }, - typeParameterFactory - ) - - fun declareGlobalTypeParameter( - signature: IdSignature, - symbolFactory: () -> IrTypeParameterSymbol, - typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter ): IrTypeParameter { - return globalTypeParameterSymbolTable.declare(signature, symbolFactory, typeParameterFactory) + return descriptorExtension.declareGlobalTypeParameter(startOffset, endOffset, origin, descriptor) } @ObsoleteDescriptorBasedAPI @@ -1009,35 +748,11 @@ open class SymbolTable( endOffset: Int, origin: IrDeclarationOrigin, descriptor: TypeParameterDescriptor, - typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter = { - irFactory.createTypeParameter( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = nameProvider.nameForDeclaration(descriptor), - symbol = it, - variance = it.descriptor.variance, - index = it.descriptor.index, - isReified = it.descriptor.isReified - ) - } - ): IrTypeParameter = - scopedTypeParameterSymbolTable.declare( - descriptor, - { signature -> createTypeParameterSymbol(descriptor, signature) }, - typeParameterFactory - ) - - fun declareScopedTypeParameter( - signature: IdSignature, - symbolFactory: (IdSignature) -> IrTypeParameterSymbol, - typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter + typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter, ): IrTypeParameter { - return typeParameterFactory(symbolFactory(signature)) + return descriptorExtension.declareScopedTypeParameter(startOffset, endOffset, origin, descriptor, typeParameterFactory) } - val unboundTypeParameters: Set get() = globalTypeParameterSymbolTable.unboundSymbols - @ObsoleteDescriptorBasedAPI fun declareValueParameter( startOffset: Int, @@ -1049,53 +764,46 @@ open class SymbolTable( name: Name? = null, index: Int? = null, isAssignable: Boolean = false, - valueParameterFactory: (IrValueParameterSymbol) -> IrValueParameter = { - irFactory.createValueParameter( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = name ?: nameProvider.nameForDeclaration(descriptor), - type = type, - isAssignable = isAssignable, - symbol = it, - index = index ?: descriptor.indexOrMinusOne, - varargElementType = varargElementType, - isCrossinline = descriptor.isCrossinline, - isNoinline = descriptor.isNoinline, - isHidden = false, - ) - } - ): IrValueParameter = - valueParameterSymbolTable.declareLocal( + valueParameterFactory: (IrValueParameterSymbol) -> IrValueParameter, + ): IrValueParameter { + return descriptorExtension.declareValueParameter( + startOffset, + endOffset, + origin, descriptor, - { IrValueParameterSymbolImpl(descriptor) }, + type, + varargElementType, + name, + index, + isAssignable, valueParameterFactory ) + } @OptIn(ObsoleteDescriptorBasedAPI::class) fun introduceValueParameter(irValueParameter: IrValueParameter) { - valueParameterSymbolTable.introduceLocal(irValueParameter.descriptor, irValueParameter.symbol) + descriptorExtension.introduceValueParameter(irValueParameter) } @ObsoleteDescriptorBasedAPI - override fun referenceValueParameter(descriptor: ParameterDescriptor) = - valueParameterSymbolTable.referenced(descriptor) { - throw AssertionError("Undefined parameter referenced: $descriptor\n${valueParameterSymbolTable.dump()}") - } + open fun referenceValue(value: ValueDescriptor): IrValueSymbol { + return descriptorExtension.referenceValue(value) + } @ObsoleteDescriptorBasedAPI - override fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol = - scopedTypeParameterSymbolTable.get(classifier, signaturer.composeSignature(classifier)) - ?: globalTypeParameterSymbolTable.referenced(classifier) { signature -> createTypeParameterSymbol(classifier, signature) } + override fun referenceValueParameter(descriptor: ParameterDescriptor): IrValueParameterSymbol { + return descriptorExtension.referenceValueParameter(descriptor) + } @ObsoleteDescriptorBasedAPI - override fun referenceScopedTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol = - scopedTypeParameterSymbolTable.referenced(classifier) { signature -> createTypeParameterSymbol(classifier, signature) } + override fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol { + return descriptorExtension.referenceTypeParameter(classifier) + } - override fun referenceTypeParameter(signature: IdSignature): IrTypeParameterSymbol = - globalTypeParameterSymbolTable.referenced(signature) { - if (signature.isPubliclyVisible) IrTypeParameterPublicSymbolImpl(signature) else IrTypeParameterSymbolImpl() - } + @ObsoleteDescriptorBasedAPI + override fun referenceScopedTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol { + return descriptorExtension.referenceScopedTypeParameter(classifier) + } @ObsoleteDescriptorBasedAPI fun declareVariable( @@ -1104,18 +812,10 @@ open class SymbolTable( origin: IrDeclarationOrigin, descriptor: VariableDescriptor, type: IrType, - variableFactory: (IrVariableSymbol) -> IrVariable = { - IrVariableImpl( - startOffset, endOffset, origin, it, nameProvider.nameForDeclaration(descriptor), type, - descriptor.isVar, descriptor.isConst, descriptor.isLateInit - ) - } - ): IrVariable = - variableSymbolTable.declareLocal( - descriptor, - { IrVariableSymbolImpl(descriptor) }, - variableFactory - ) + variableFactory: (IrVariableSymbol) -> IrVariable, + ): IrVariable { + return descriptorExtension.declareVariable(startOffset, endOffset, origin, descriptor, type, variableFactory) + } @ObsoleteDescriptorBasedAPI fun declareVariable( @@ -1124,11 +824,10 @@ open class SymbolTable( origin: IrDeclarationOrigin, descriptor: VariableDescriptor, type: IrType, - irInitializerExpression: IrExpression? - ): IrVariable = - declareVariable(startOffset, endOffset, origin, descriptor, type).apply { - initializer = irInitializerExpression - } + irInitializerExpression: IrExpression?, + ): IrVariable { + return descriptorExtension.declareVariable(startOffset, endOffset, origin, descriptor, type, irInitializerExpression) + } @ObsoleteDescriptorBasedAPI fun declareLocalDelegatedProperty( @@ -1137,82 +836,14 @@ open class SymbolTable( origin: IrDeclarationOrigin, descriptor: VariableDescriptorWithAccessors, type: IrType, - factory: (IrLocalDelegatedPropertySymbol) -> IrLocalDelegatedProperty = { - irFactory.createLocalDelegatedProperty( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - name = nameProvider.nameForDeclaration(descriptor), - symbol = it, - type = type, - isVar = descriptor.isVar - ) - } - ): IrLocalDelegatedProperty = - localDelegatedPropertySymbolTable.declareLocal( - descriptor, - { IrLocalDelegatedPropertySymbolImpl(descriptor) }, - factory - ).apply { - metadata = DescriptorMetadataSource.LocalDelegatedProperty(descriptor) - } - - @ObsoleteDescriptorBasedAPI - fun referenceLocalDelegatedProperty(descriptor: VariableDescriptorWithAccessors) = - localDelegatedPropertySymbolTable.referenced(descriptor) { - throw AssertionError("Undefined local delegated property referenced: $descriptor") - } - - override fun enterScope(symbol: IrSymbol) { - scopedSymbolTables.forEach { it.enterScope(symbol) } - } - - override fun enterScope(owner: IrDeclaration) { - enterScope(owner.symbol) - } - - override fun leaveScope(symbol: IrSymbol) { - scopedSymbolTables.forEach { it.leaveScope(symbol) } - } - - override fun leaveScope(owner: IrDeclaration) { - leaveScope(owner.symbol) + factory: (IrLocalDelegatedPropertySymbol) -> IrLocalDelegatedProperty, + ): IrLocalDelegatedProperty { + return descriptorExtension.declareLocalDelegatedProperty(startOffset, endOffset, origin, descriptor, type, factory) } @ObsoleteDescriptorBasedAPI - open fun referenceValue(value: ValueDescriptor): IrValueSymbol = - when (value) { - is ParameterDescriptor -> - valueParameterSymbolTable.referenced(value) { throw AssertionError("Undefined parameter referenced: $value") } - is VariableDescriptor -> - variableSymbolTable.referenced(value) { throw AssertionError("Undefined variable referenced: $value") } - else -> - throw IllegalArgumentException("Unexpected value descriptor: $value") - } - - private inline fun FlatSymbolTable.forEachSymbolImpl(block: (IrSymbol) -> Unit) - where Descriptor : DeclarationDescriptor, - Owner : IrSymbolOwner, - Symbol : IrBindableSymbol { - idSignatureToSymbol.forEach { (_, symbol) -> - block(symbol) - } - } - - /** - * This function is quite messy and doesn't have good contract of what exactly is traversed. - * Basic idea is it traverse symbols which can be reasonable referered from other module - * - * Be careful when using it, and avoid it, except really need. - */ - fun forEachDeclarationSymbol(block: (IrSymbol) -> Unit) { - classSymbolTable.forEachSymbolImpl { block(it) } - constructorSymbolTable.forEachSymbolImpl { block(it) } - simpleFunctionSymbolTable.forEachSymbolImpl { block(it) } - propertySymbolTable.forEachSymbolImpl { block(it) } - enumEntrySymbolTable.forEachSymbolImpl { block(it) } - typeAliasSymbolTable.forEachSymbolImpl { block(it) } - fieldSymbolTable.forEachSymbolImpl { block(it) } + fun referenceLocalDelegatedProperty(descriptor: VariableDescriptorWithAccessors): IrLocalDelegatedPropertySymbol { + return descriptorExtension.referenceLocalDelegatedProperty(descriptor) } } @@ -1236,19 +867,3 @@ inline fun ReferenceSymbolTable.withReferenceScope(owner: IrDeclaration, blo leaveScope(owner) return result } - -val SymbolTable.allUnbound: Set - get() = buildSet { - fun addUnbound(symbols: Collection) { - symbols.filterTo(this) { !it.isBound } - } - - addUnbound(unboundClasses) - addUnbound(unboundConstructors) - addUnbound(unboundEnumEntries) - addUnbound(unboundFields) - addUnbound(unboundSimpleFunctions) - addUnbound(unboundProperties) - addUnbound(unboundTypeAliases) - addUnbound(unboundTypeParameters) - } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTableExtension.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTableExtension.kt new file mode 100644 index 00000000000..6d2fb3dc70b --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTableExtension.kt @@ -0,0 +1,695 @@ +/* + * 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.ir.util + +import org.jetbrains.kotlin.descriptors.DescriptorVisibility +import org.jetbrains.kotlin.ir.IrLock +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrExpressionBody +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.utils.threadLocal + +abstract class ReferenceSymbolTableExtension { + abstract fun referenceScript(descriptor: Script): IrScriptSymbol + abstract fun referenceClass(descriptor: Class): IrClassSymbol + abstract fun referenceConstructor(descriptor: Constructor): IrConstructorSymbol + abstract fun referenceEnumEntry(descriptor: Class): IrEnumEntrySymbol + abstract fun referenceField(descriptor: Property): IrFieldSymbol + abstract fun referenceProperty(descriptor: Property): IrPropertySymbol + abstract fun referenceSimpleFunction(descriptor: Function): IrSimpleFunctionSymbol + abstract fun referenceDeclaredFunction(descriptor: Function): IrSimpleFunctionSymbol + abstract fun referenceValueParameter(descriptor: ValueParameter): IrValueParameterSymbol + abstract fun referenceTypeParameter(classifier: TypeParameter): IrTypeParameterSymbol + abstract fun referenceScopedTypeParameter(classifier: TypeParameter): IrTypeParameterSymbol + abstract fun referenceTypeAlias(descriptor: TypeAlias): IrTypeAliasSymbol +} + +typealias SymbolFactory = (Declaration, IdSignature?) -> Symbol +typealias OwnerFactory = (Symbol) -> SymbolOwner + +abstract class SymbolTableExtension< + Declaration, Class, TypeAlias, Script, Function, Constructor, + Property, ValueParameter, TypeParameter, + >( + val table: SymbolTable, +) : ReferenceSymbolTableExtension() + where Class : Declaration, + TypeAlias : Declaration, + Script : Declaration, + Function : Declaration, + Constructor : Declaration, + Property : Declaration, + ValueParameter : Declaration, + TypeParameter : Declaration { + protected val lock: IrLock + get() = table.lock + + private val scriptSlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + private val classSlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + private val constructorSlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + private val enumEntrySlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + private val fieldSlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + private val functionSlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + private val propertySlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + private val typeAliasSlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + private val globalTypeParameterSlice: SymbolTableSlice.Flat = + SymbolTableSlice.Flat(lock) + + private val scopedTypeParameterSlice: SymbolTableSlice.Scoped by threadLocal { + SymbolTableSlice.Scoped(lock) + } + + protected abstract fun MutableList>.initializeScopedSlices() + + private val scopedSlices: List> by lazy(LazyThreadSafetyMode.PUBLICATION) { + buildList { + add(scopedTypeParameterSlice) + initializeScopedSlices() + } + } + + // ------------------------------------ signature ------------------------------------ + + protected abstract fun calculateSignature(declaration: Declaration): IdSignature? + protected abstract fun calculateEnumEntrySignature(declaration: Class): IdSignature? + protected abstract fun calculateFieldSignature(declaration: Property): IdSignature? + + // ------------------------------------ script ------------------------------------ + + fun declareScript( + startOffset: Int, + endOffset: Int, + descriptor: Script, + ): IrScript { + return declare( + descriptor, + scriptSlice, + SymbolTable::declareScript, + symbolFactory = { createScriptSymbol(descriptor, it) }, + ownerFactory = { defaultScriptFactory(startOffset, endOffset, descriptor, it) } + ) + } + + override fun referenceScript(descriptor: Script): IrScriptSymbol { + return scriptSlice.referenced(descriptor) { createScriptSymbol(descriptor, signature = null) } + } + + protected abstract fun defaultScriptFactory(startOffset: Int, endOffset: Int, script: Script, symbol: IrScriptSymbol): IrScript + + protected abstract fun createScriptSymbol(descriptor: Script, signature: IdSignature?): IrScriptSymbol + + // ------------------------------------ script ------------------------------------ + + fun declareClass(descriptor: Class, classFactory: (IrClassSymbol) -> IrClass): IrClass { + return declare( + descriptor, + classSlice, + SymbolTable::declareClass, + { createClassSymbol(descriptor, it) }, + classFactory + ) + } + + fun declareClassIfNotExists(descriptor: Class, classFactory: (IrClassSymbol) -> IrClass): IrClass { + return declareIfNotExist( + descriptor, + classSlice, + SymbolTable::declareClassIfNotExists, + { createClassSymbol(descriptor, it) }, + classFactory + ) + } + + override fun referenceClass(descriptor: Class): IrClassSymbol { + return reference( + descriptor, + classSlice, + SymbolTable::referenceClassImpl, + ::createClassSymbol, + ::createPublicClassSymbol, + ::createPrivateClassSymbol + ) + } + + protected fun createClassSymbol(descriptor: Class, signature: IdSignature?): IrClassSymbol { + return signature?.let { createPublicClassSymbol(descriptor, signature) } ?: createPrivateClassSymbol(descriptor) + } + + protected abstract fun createPublicClassSymbol(descriptor: Class, signature: IdSignature): IrClassSymbol + protected abstract fun createPrivateClassSymbol(descriptor: Class): IrClassSymbol + + // ------------------------------------ constructor ------------------------------------ + + fun declareConstructor(descriptor: Constructor, constructorFactory: (IrConstructorSymbol) -> IrConstructor): IrConstructor { + return declare( + descriptor, + constructorSlice, + SymbolTable::declareConstructor, + { createConstructorSymbol(descriptor, it) }, + constructorFactory + ) + } + + fun declareConstructorIfNotExists( + descriptor: Constructor, + constructorFactory: (IrConstructorSymbol) -> IrConstructor, + ): IrConstructor { + return declareIfNotExist( + descriptor, + constructorSlice, + SymbolTable::declareConstructorIfNotExists, + { createConstructorSymbol(descriptor, it) }, + constructorFactory + ) + } + + override fun referenceConstructor(descriptor: Constructor): IrConstructorSymbol { + return reference( + descriptor, + constructorSlice, + SymbolTable::referenceConstructorImpl, + ::createConstructorSymbol, + ::createPublicConstructorSymbol, + ::createPrivateConstructorSymbol + ) + } + + protected fun createConstructorSymbol(descriptor: Constructor, signature: IdSignature?): IrConstructorSymbol { + return signature?.let { createPublicConstructorSymbol(descriptor, signature) } ?: createPrivateConstructorSymbol(descriptor) + } + + protected abstract fun createPublicConstructorSymbol(descriptor: Constructor, signature: IdSignature): IrConstructorSymbol + protected abstract fun createPrivateConstructorSymbol(descriptor: Constructor): IrConstructorSymbol + + // ------------------------------------ enum entry ------------------------------------ + + fun declareEnumEntry(descriptor: Class, enumEntryFactory: (IrEnumEntrySymbol) -> IrEnumEntry): IrEnumEntry { + return declare( + descriptor, + enumEntrySlice, + SymbolTable::declareEnumEntry, + { createEnumEntrySymbol(descriptor, it) }, + enumEntryFactory, + ::calculateEnumEntrySignature + ) + } + + fun declareEnumEntry(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: Class): IrEnumEntry { + return declareEnumEntry( + descriptor + ) { enumEntrySymbol -> defaultEnumEntryFactory(startOffset, endOffset, origin, descriptor, enumEntrySymbol) } + } + + fun declareEnumEntryIfNotExists(descriptor: Class, enumEntryFactory: (IrEnumEntrySymbol) -> IrEnumEntry): IrEnumEntry { + return declareIfNotExist( + descriptor, + enumEntrySlice, + SymbolTable::declareEnumEntryIfNotExists, + { createEnumEntrySymbol(descriptor, it) }, + enumEntryFactory, + ::calculateEnumEntrySignature + ) + } + + override fun referenceEnumEntry(descriptor: Class): IrEnumEntrySymbol { + return reference( + descriptor, + enumEntrySlice, + SymbolTable::referenceEnumEntryImpl, + ::createEnumEntrySymbol, + ::createPublicEnumEntrySymbol, + ::createPrivateEnumEntrySymbol, + ::calculateEnumEntrySignature + ) + } + + protected fun createEnumEntrySymbol(descriptor: Class, signature: IdSignature?): IrEnumEntrySymbol { + return signature?.let { createPublicEnumEntrySymbol(descriptor, signature) } ?: createPrivateEnumEntrySymbol(descriptor) + } + + protected abstract fun createPublicEnumEntrySymbol(descriptor: Class, signature: IdSignature): IrEnumEntrySymbol + protected abstract fun createPrivateEnumEntrySymbol(descriptor: Class): IrEnumEntrySymbol + + protected abstract fun defaultEnumEntryFactory( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + enumEntry: Class, + symbol: IrEnumEntrySymbol, + ): IrEnumEntry + + // ------------------------------------ field ------------------------------------ + + fun declareField( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: Property, + type: IrType, + visibility: DescriptorVisibility? = null, + fieldFactory: (IrFieldSymbol) -> IrField = { + defaultFieldFactory( + startOffset, + endOffset, + origin, + descriptor, + type, + visibility, + it + ) + }, + ): IrField { + return declare( + descriptor, + fieldSlice, + SymbolTable::declareField, + { createFieldSymbol(descriptor, it) }, + fieldFactory, + ::calculateFieldSignature + ) + } + + fun declareField( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: Property, + type: IrType, + irInitializer: IrExpressionBody?, + ): IrField { + return declareField(startOffset, endOffset, origin, descriptor, type).apply { + initializer = irInitializer + } + } + + override fun referenceField(descriptor: Property): IrFieldSymbol { + return reference( + descriptor, + fieldSlice, + SymbolTable::referenceFieldImpl, + ::createFieldSymbol, + ::createPublicFieldSymbol, + ::createPrivateFieldSymbol, + ::calculateFieldSignature + ) + } + + protected fun createFieldSymbol(descriptor: Property, signature: IdSignature?): IrFieldSymbol { + return signature?.let { createPublicFieldSymbol(descriptor, signature) } ?: createPrivateFieldSymbol(descriptor) + } + + protected abstract fun createPublicFieldSymbol(descriptor: Property, signature: IdSignature): IrFieldSymbol + protected abstract fun createPrivateFieldSymbol(descriptor: Property): IrFieldSymbol + + protected abstract fun defaultFieldFactory( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: Property, + type: IrType, + visibility: DescriptorVisibility?, + symbol: IrFieldSymbol, + ): IrField + + // ------------------------------------ property ------------------------------------ + + fun declareProperty(descriptor: Property, propertyFactory: (IrPropertySymbol) -> IrProperty): IrProperty { + return declare( + descriptor, + propertySlice, + SymbolTable::declareProperty, + { createPropertySymbol(descriptor, it) }, + propertyFactory + ) + } + + fun declareProperty( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: Property, + isDelegated: Boolean,/* = descriptor.isDelegated*/ + ): IrProperty { + return declareProperty(descriptor) { propertySymbol -> + defaultPropertyFactory(startOffset, endOffset, origin, descriptor, isDelegated, propertySymbol) + } + } + + fun declarePropertyIfNotExists(descriptor: Property, propertyFactory: (IrPropertySymbol) -> IrProperty): IrProperty { + return declareIfNotExist( + descriptor, + propertySlice, + SymbolTable::declarePropertyIfNotExists, + { createPropertySymbol(descriptor, it) }, + propertyFactory + ) + } + + override fun referenceProperty(descriptor: Property): IrPropertySymbol { + return reference( + descriptor, + propertySlice, + SymbolTable::referencePropertyImpl, + ::createPropertySymbol, + ::createPublicPropertySymbol, + ::createPrivatePropertySymbol + ) + } + + protected fun createPropertySymbol(descriptor: Property, signature: IdSignature?): IrPropertySymbol { + return signature?.let { createPublicPropertySymbol(descriptor, signature) } ?: createPrivatePropertySymbol(descriptor) + } + + protected abstract fun createPublicPropertySymbol(descriptor: Property, signature: IdSignature): IrPropertySymbol + protected abstract fun createPrivatePropertySymbol(descriptor: Property): IrPropertySymbol + + protected abstract fun defaultPropertyFactory( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: Property, + isDelegated: Boolean, + symbol: IrPropertySymbol, + ): IrProperty + + // ------------------------------------ typealias ------------------------------------ + + fun declareTypeAlias(descriptor: TypeAlias, typeAliasFactory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias { + return declare( + descriptor, + typeAliasSlice, + SymbolTable::declareTypeAlias, + { createTypeAliasSymbol(descriptor, it) }, + typeAliasFactory + ) + } + + fun declareTypeAliasIfNotExists(descriptor: TypeAlias, typeAliasFactory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias { + return declareIfNotExist( + descriptor, + typeAliasSlice, + SymbolTable::declareTypeAliasIfNotExists, + { createTypeAliasSymbol(descriptor, it) }, + typeAliasFactory + ) + } + + override fun referenceTypeAlias(descriptor: TypeAlias): IrTypeAliasSymbol { + return reference( + descriptor, + typeAliasSlice, + SymbolTable::referenceTypeAliasImpl, + ::createTypeAliasSymbol, + ::createPublicTypeAliasSymbol, + ::createPrivateTypeAliasSymbol + ) + } + + protected fun createTypeAliasSymbol(descriptor: TypeAlias, signature: IdSignature?): IrTypeAliasSymbol { + return signature?.let { createPublicTypeAliasSymbol(descriptor, signature) } ?: createPrivateTypeAliasSymbol(descriptor) + } + + protected abstract fun createPublicTypeAliasSymbol(descriptor: TypeAlias, signature: IdSignature): IrTypeAliasSymbol + protected abstract fun createPrivateTypeAliasSymbol(descriptor: TypeAlias): IrTypeAliasSymbol + + // ------------------------------------ function ------------------------------------ + + fun declareSimpleFunction(descriptor: Function, functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunction { + return declare( + descriptor, + functionSlice, + SymbolTable::declareSimpleFunction, + { createFunctionSymbol(descriptor, it) }, + functionFactory + ) + } + + fun declareSimpleFunctionIfNotExists( + descriptor: Function, + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction, + ): IrSimpleFunction { + return declareIfNotExist( + descriptor, + functionSlice, + SymbolTable::declareSimpleFunctionIfNotExists, + { createFunctionSymbol(descriptor, it) }, + functionFactory + ) + } + + override fun referenceSimpleFunction(descriptor: Function): IrSimpleFunctionSymbol { + return reference( + descriptor, + functionSlice, + SymbolTable::referenceSimpleFunctionImpl, + ::createFunctionSymbol, + ::createPublicFunctionSymbol, + ::createPrivateFunctionSymbol + ) + } + + override fun referenceDeclaredFunction(descriptor: Function): IrSimpleFunctionSymbol { + fun throwError(): Nothing = error("Function is not declared: $descriptor") + + return reference( + descriptor, + functionSlice, + SymbolTable::referenceSimpleFunctionImpl, + { _, _ -> throwError() }, + { _, _ -> throwError() }, + { throwError() }, + ) + } + + protected fun createFunctionSymbol(descriptor: Function, signature: IdSignature?): IrSimpleFunctionSymbol { + return signature?.let { createPublicFunctionSymbol(descriptor, signature) } ?: createPrivateFunctionSymbol(descriptor) + } + + protected abstract fun createPublicFunctionSymbol(descriptor: Function, signature: IdSignature): IrSimpleFunctionSymbol + protected abstract fun createPrivateFunctionSymbol(descriptor: Function): IrSimpleFunctionSymbol + + // ------------------------------------ type parameter ------------------------------------ + + fun declareGlobalTypeParameter( + descriptor: TypeParameter, + typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter, + ): IrTypeParameter { + return declare( + descriptor, + globalTypeParameterSlice, + SymbolTable::declareGlobalTypeParameter, + { createTypeParameterSymbol(descriptor, it) }, + typeParameterFactory + ) + } + + fun declareGlobalTypeParameter( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: TypeParameter, + ): IrTypeParameter { + return declareGlobalTypeParameter(descriptor) { + defaultTypeParameterFactory(startOffset, endOffset, origin, descriptor, it) + } + } + + fun declareScopedTypeParameter( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: TypeParameter, + typeParameterFactory: (IrTypeParameterSymbol) -> IrTypeParameter = { + defaultTypeParameterFactory(startOffset, endOffset, origin, descriptor, it) + }, + ): IrTypeParameter { + // TODO: looks little suspicious + // Is it correct that we never create scoped type parameters by signatures? + return scopedTypeParameterSlice.declare( + descriptor, + { createTypeParameterSymbol(descriptor, calculateSignature(descriptor)) }, + typeParameterFactory + ) + } + + override fun referenceTypeParameter(classifier: TypeParameter): IrTypeParameterSymbol { + scopedTypeParameterSlice.get(classifier)?.let { return it } + return reference( + classifier, + globalTypeParameterSlice, + SymbolTable::referenceTypeParameterImpl, + ::createTypeParameterSymbol, + ::createPublicTypeParameterSymbol, + ::createPrivateTypeParameterSymbol + ) + } + + override fun referenceScopedTypeParameter(classifier: TypeParameter): IrTypeParameterSymbol { + return scopedTypeParameterSlice.referenced(classifier) { createTypeParameterSymbol(classifier, calculateSignature(classifier)) } + } + + protected fun createTypeParameterSymbol(descriptor: TypeParameter, signature: IdSignature?): IrTypeParameterSymbol { + return signature?.let { createPublicTypeParameterSymbol(descriptor, signature) } ?: createPrivateTypeParameterSymbol(descriptor) + } + + protected abstract fun createPublicTypeParameterSymbol(descriptor: TypeParameter, signature: IdSignature): IrTypeParameterSymbol + protected abstract fun createPrivateTypeParameterSymbol(descriptor: TypeParameter): IrTypeParameterSymbol + + protected abstract fun defaultTypeParameterFactory( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + descriptor: TypeParameter, + symbol: IrTypeParameterSymbol, + ): IrTypeParameter + + // ------------------------------------ value parameter ------------------------------------ + + override fun referenceValueParameter(descriptor: ValueParameter): IrValueParameterSymbol { + error("There is no default implementation for any symbol table extension") + } + + // ------------------------------------ scopes ------------------------------------ + + fun enterScope(symbol: IrSymbol) { + scopedSlices.forEach { it.enterScope(symbol) } + } + + fun enterScope(owner: IrDeclaration) { + enterScope(owner.symbol) + } + + fun leaveScope(symbol: IrSymbol) { + scopedSlices.forEach { it.leaveScope(symbol) } + } + + fun leaveScope(owner: IrDeclaration) { + leaveScope(owner.symbol) + } + + // ------------------------------------ utilities ------------------------------------ + + /** + * This function is quite messy and doesn't have good contract of what exactly is traversed. + * Basic idea is it traverse symbols which can be reasonable referered from other module + * + * Be careful when using it, and avoid it, except really need. + * + * TODO: add some OptIn + */ + fun forEachDeclarationSymbol(block: (IrSymbol) -> Unit) { + table.forEachDeclarationSymbol(block) + + scriptSlice.forEachSymbol { block(it) } + classSlice.forEachSymbol { block(it) } + constructorSlice.forEachSymbol { block(it) } + enumEntrySlice.forEachSymbol { block(it) } + fieldSlice.forEachSymbol { block(it) } + functionSlice.forEachSymbol { block(it) } + propertySlice.forEachSymbol { block(it) } + typeAliasSlice.forEachSymbol { block(it) } + globalTypeParameterSlice.forEachSymbol { block(it) } + } + + val allUnboundSymbols: Set + get() = buildSet { + fun addUnbound(slice: SymbolTableSlice<*, *, *>) { + slice.unboundSymbols.filterTo(this) { !it.isBound } + } + addAll(table.allUnboundSymbols) + + addUnbound(scriptSlice) + addUnbound(classSlice) + addUnbound(constructorSlice) + addUnbound(enumEntrySlice) + addUnbound(fieldSlice) + addUnbound(functionSlice) + addUnbound(propertySlice) + addUnbound(typeAliasSlice) + addUnbound(globalTypeParameterSlice) + } + + private inline fun , SymbolOwner : IrSymbolOwner> declare( + descriptor: D, + slice: SymbolTableSlice, + declareBySignature: SymbolTable.(IdSignature, () -> Symbol, OwnerFactory) -> SymbolOwner, + crossinline symbolFactory: (IdSignature?) -> Symbol, + noinline ownerFactory: OwnerFactory, + specificCalculateSignature: (D) -> IdSignature? = { calculateSignature(it) } + ): SymbolOwner { + return declare( + descriptor, + slice, + declareBySignature, + SymbolTableSlice::declare, + symbolFactory, + ownerFactory, + specificCalculateSignature + ) + } + + private inline fun , SymbolOwner : IrSymbolOwner> declareIfNotExist( + descriptor: D, + slice: SymbolTableSlice, + declareBySignature: SymbolTable.(IdSignature, () -> Symbol, OwnerFactory) -> SymbolOwner, + crossinline symbolFactory: (IdSignature?) -> Symbol, + noinline ownerFactory: OwnerFactory, + specificCalculateSignature: (D) -> IdSignature? = { calculateSignature(it) } + ): SymbolOwner { + return declare( + descriptor, + slice, + declareBySignature, + SymbolTableSlice::declareIfNotExists, + symbolFactory, + ownerFactory, + specificCalculateSignature + ) + } + + private inline fun , SymbolOwner : IrSymbolOwner> declare( + descriptor: D, + slice: SymbolTableSlice, + declareBySignature: SymbolTable.(IdSignature, () -> Symbol, OwnerFactory) -> SymbolOwner, + declareByDeclaration: SymbolTableSlice.(D, () -> Symbol, OwnerFactory) -> SymbolOwner, + crossinline symbolFactory: (IdSignature?) -> Symbol, + noinline ownerFactory: OwnerFactory, + specificCalculateSignature: (D) -> IdSignature? + ): SymbolOwner { + return when (val signature = specificCalculateSignature(descriptor)) { + null -> slice.declareByDeclaration(descriptor, { symbolFactory(signature) }, ownerFactory) + else -> table.declareBySignature(signature, { symbolFactory(signature) }, ownerFactory) + } + } + + private inline fun , SymbolOwner : IrSymbolOwner> reference( + descriptor: D, + slice: SymbolTableSlice, + referenceBySignature: SymbolTable.(IdSignature, () -> Symbol, () -> Symbol) -> Symbol, + crossinline symbolFactory: (D, IdSignature?) -> Symbol, + crossinline publicSymbolFactory: (D, IdSignature) -> Symbol, + crossinline privateSymbolFactory: (D) -> Symbol, + specificCalculateSignature: (D) -> IdSignature? = { calculateSignature(it) } + ): Symbol { + return when (val signature = specificCalculateSignature(descriptor)) { + null -> slice.referenced(descriptor) { symbolFactory(descriptor, signature) } + else -> table.referenceBySignature( + signature, + { publicSymbolFactory(descriptor, signature) }, + { privateSymbolFactory(descriptor) } + ) + } + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTableSlice.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTableSlice.kt new file mode 100644 index 00000000000..8d2e26d19ca --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTableSlice.kt @@ -0,0 +1,195 @@ +/* + * 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.ir.util + +import org.jetbrains.kotlin.ir.IrLock +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner +import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol + +abstract class SymbolTableSlice(val lock: IrLock) + where SymbolOwner : IrSymbolOwner, + Symbol : IrBindableSymbol<*, SymbolOwner> { + /** + * With the partial linkage turned on it's hard to predict whether a newly created [IrSymbol] that is added to the [SymbolTable] + * via one of referenceXXX() calls will or won't be bound to some declaration. The latter may happen in certain cases, + * for example when the symbol refers from an IR expression to a non-top level declaration that was removed in newer version + * of Kotlin library (KLIB). Unless such symbol is registered as "probably unbound" it remains invisible for the linkage process. + * + * The optimization that allows to reference symbols without registering them as "probably unbound" is fragile. It's better + * to avoid calling any referenceXXX(reg = false) functions. Instead, wherever it is s suitable it is recommended to use one + * of the appropriate declareXXX() calls. + * + * For the future: Consider implementing the optimization once again for the new "flat" ID signatures. + */ + val unboundSymbols = linkedSetOf() + + abstract fun get(key: Key): Symbol? + abstract fun set(key: Key, symbol: Symbol) + + inline fun declare(key: Key, createSymbol: () -> Symbol, createOwner: (Symbol) -> SymbolOwner): SymbolOwner { + synchronized(lock) { + val existing = get(key) + val symbol = if (existing == null) { + createSymbol().also { set(key, it) } + } else { + unboundSymbols.remove(existing) + existing + } + return createOwnerSafe(symbol, createOwner) + } + } + + inline fun referenced(key: Key, orElse: () -> Symbol): Symbol { + synchronized(lock) { + return get(key) ?: run { + val new = orElse() + assert(unboundSymbols.add(new)) { "Symbol for ${new.signature} was already referenced" } + set(key, new) + new + } + } + } + + inline fun declareIfNotExists( + key: Key, + createSymbol: () -> Symbol, + createOwner: (Symbol) -> SymbolOwner, + ): SymbolOwner { + synchronized(lock) { + val existing = get(key) + val symbol = if (existing == null) { + // checkOriginal(descriptor) // TODO: remove? + val new = createSymbol() + set(key, new) + new + } else { + if (existing.isBound) { + unboundSymbols.remove(existing) + return existing.owner + } + existing + } + return createOwnerSafe(symbol, createOwner) + } + } + + // TODO: add PrivateToInline + @PublishedApi + internal inline fun createOwnerSafe(symbol: Symbol, createOwner: (Symbol) -> SymbolOwner): SymbolOwner { + val owner = createOwner(symbol) + require(symbol.isBound) + require(symbol.owner === owner) { + "Attempt to rebind an IR symbol or to re-create its owner: old owner ${symbol.owner.render()}, new owner ${owner.render()}" + } + return owner + } + + class Flat(lock: IrLock) : SymbolTableSlice(lock) + where SymbolOwner : IrSymbolOwner, Symbol : IrBindableSymbol<*, SymbolOwner> { + private val signatureToSymbol = hashMapOf() + + override fun get(key: Key): Symbol? { + return signatureToSymbol[key] + } + + override fun set(key: Key, symbol: Symbol) { + signatureToSymbol[key] = symbol + } + + // TODO: add some OptIn + internal fun forEachSymbol(block: (IrSymbol) -> Unit) { + signatureToSymbol.forEach { (_, symbol) -> block(symbol) } + } + } + + class Scoped(lock: IrLock) : SymbolTableSlice(lock) + where SymbolOwner : IrSymbolOwner, Symbol : IrBindableSymbol<*, SymbolOwner> { + + override fun set(key: Key, symbol: Symbol) { + val scope = currentScope ?: noScope() + scope[key] = symbol + } + + @PublishedApi + // TODO: add PrivateForInline + internal var currentScope: SliceScope? = null + private set + + override fun get(key: Key): Symbol? { + return currentScope?.get(key) + } + + inline fun declareLocal(key: Key, createSymbol: () -> Symbol, createOwner: (Symbol) -> SymbolOwner): SymbolOwner { + val scope = currentScope ?: noScope() + val symbol = scope.getLocal(key) ?: createSymbol().also { scope[key] = it } + return createOwnerSafe(symbol, createOwner) + } + + fun introduceLocal(descriptor: Key, symbol: Symbol) { + val scope = currentScope ?: noScope() + scope[descriptor]?.let { error("$descriptor is already bound to $it") } + scope[descriptor] = symbol + } + + fun enterScope(owner: IrSymbol) { + currentScope = SliceScope(owner, currentScope) + } + + fun leaveScope(owner: IrSymbol) { + currentScope?.owner.let { + require(it == owner) { "Unexpected leaveScope: owner=$owner, currentScope.owner=$it" } + } + + currentScope = currentScope?.parent + + if (currentScope != null && unboundSymbols.isNotEmpty()) { + @OptIn(ObsoleteDescriptorBasedAPI::class) + error("Local scope contains unbound symbols: ${unboundSymbols.joinToString { it.descriptor.toString() }}") + } + } + + fun dump(): String { + return currentScope?.dump() ?: "" + } + + @PublishedApi + // TODO: add PrivateForInline + internal fun noScope(): Nothing = error("No active scope") + + @PublishedApi + // TODO: add PrivateForInline + internal class SliceScope(val owner: IrSymbol, val parent: SliceScope?) { + private val signatureToSymbol = hashMapOf() + + operator fun get(descriptor: Key): Symbol? { + return signatureToSymbol[descriptor] ?: parent?.get(descriptor) + } + + fun getLocal(descriptor: Key): Symbol? { + return signatureToSymbol[descriptor] + } + + operator fun set(descriptor: Key, symbol: Symbol) { + signatureToSymbol[descriptor] = symbol + } + + fun dumpTo(stringBuilder: StringBuilder): StringBuilder { + return stringBuilder.also { + it.append("owner=") + it.append(owner) + it.append("; ") + signatureToSymbol.keys.joinTo(prefix = "[", postfix = "]", buffer = it) + it.append('\n') + parent?.dumpTo(it) + } + } + + fun dump(): String = dumpTo(StringBuilder()).toString() + } + } +} diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/checks.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/checks.kt index afe2fec85fc..f834cae01fa 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/checks.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/checks.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.allUnbound import org.jetbrains.kotlin.ir.util.irMessageLogger // N.B. Checks for absence of unbound symbols only when unbound symbols are not allowed. @@ -18,14 +17,14 @@ fun KotlinIrLinker.checkNoUnboundSymbols(symbolTable: SymbolTable, whenDetected: // N.B. Always checks for absence of unbound symbols. The condition whether this check should be applied is controlled outside. fun IrMessageLogger.checkNoUnboundSymbols(symbolTable: SymbolTable, whenDetected: String) { - val unboundSymbols = symbolTable.allUnbound + val unboundSymbols = symbolTable.descriptorExtension.allUnboundSymbols if (unboundSymbols.isNotEmpty()) UnexpectedUnboundIrSymbols(unboundSymbols, whenDetected).raiseIssue(this) } // N.B. Always checks for absence of unbound symbols. The condition whether this check should be applied is controlled outside. fun CompilerConfiguration.checkNoUnboundSymbols(symbolTable: SymbolTable, whenDetected: String) { - val unboundSymbols = symbolTable.allUnbound + val unboundSymbols = symbolTable.descriptorExtension.allUnboundSymbols if (unboundSymbols.isNotEmpty()) UnexpectedUnboundIrSymbols(unboundSymbols, whenDetected).raiseIssue(irMessageLogger) } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLinkerImpl.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLinkerImpl.kt index b92e4f15d8d..eb7098b947d 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLinkerImpl.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLinkerImpl.kt @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageLogger import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.allUnbound fun createPartialLinkageSupportForLinker( partialLinkageConfig: PartialLinkageConfig, @@ -73,7 +72,7 @@ internal class PartialLinkageSupportForLinkerImpl( private fun generateStubsAndPatchUsagesInternal(symbolTable: SymbolTable, patchIrTree: () -> Unit) { // Generate stubs. - for (symbol in symbolTable.allUnbound) { + for (symbol in symbolTable.descriptorExtension.allUnboundSymbols) { stubGenerator.getDeclaration(symbol) } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt index 2a85957def8..107dd34f539 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt @@ -145,7 +145,7 @@ class CurrentModuleWithICDeserializer( override fun init(delegate: IrModuleDeserializer) { val knownBuiltIns = irBuiltIns.knownBuiltins.map { (it as IrSymbolOwner).symbol }.toSet() - symbolTable.forEachDeclarationSymbol { + symbolTable.descriptorExtension.forEachDeclarationSymbol { assert(it.isPublicApi) if (it.descriptor.isDirtyDescriptor()) { // public && non-deserialized should be dirty symbol if (it !in knownBuiltIns) { @@ -172,4 +172,4 @@ class CurrentModuleWithICDeserializer( override fun fileDeserializers(): Collection { return delegate.fileDeserializers() } -} \ No newline at end of file +} diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt index 98cae5ce890..1e4ecb41bdb 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt @@ -7,12 +7,12 @@ package org.jetbrains.kotlin.test.backend.handlers import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.lazy.AbstractIrLazyFunction import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.util.DeserializableClass import org.jetbrains.kotlin.ir.util.IdSignature -import org.jetbrains.kotlin.ir.util.allUnbound import org.jetbrains.kotlin.ir.util.resolveFakeOverride import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -24,13 +24,14 @@ import org.jetbrains.kotlin.test.services.TestServices class IrInlineBodiesHandler(testServices: TestServices) : AbstractIrHandler(testServices) { val declaredInlineFunctionSignatures = mutableSetOf() + @OptIn(ObsoleteDescriptorBasedAPI::class) override fun processModule(module: TestModule, info: IrBackendInput) { info.processAllIrModuleFragments(module) { irModule, _ -> irModule.acceptChildrenVoid(InlineFunctionsCollector()) irModule.acceptChildrenVoid(InlineCallBodiesCheck(firEnabled = module.frontendKind == FrontendKinds.FIR)) } - assertions.assertTrue((info as IrBackendInput.JvmIrBackendInput).backendInput.symbolTable.allUnbound.isEmpty()) + assertions.assertTrue((info as IrBackendInput.JvmIrBackendInput).backendInput.symbolTable.descriptorExtension.allUnboundSymbols.isEmpty()) } override fun processAfterAllModules(someAssertionWasFailed: Boolean) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BuiltInFictitiousFunctionIrClassFactory.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BuiltInFictitiousFunctionIrClassFactory.kt index 762f3005830..07d22d15512 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BuiltInFictitiousFunctionIrClassFactory.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BuiltInFictitiousFunctionIrClassFactory.kt @@ -371,7 +371,7 @@ internal class BuiltInFictitiousFunctionIrClassFactory( isExpect = descriptor.isExpect, isFakeOverride = true) } - val property = symbolTable.declareProperty(offset, offset, memberOrigin, descriptor, propertyFactory = propertyDeclare) + val property = symbolTable.declareProperty(descriptor, propertyFactory = propertyDeclare) property.parent = this property.getter = descriptor.getter?.let { g -> createFakeOverrideFunction(g, property.symbol) } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt index 31f0303998b..027ecb34b9b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize import org.jetbrains.kotlin.fir.signaturer.Ir2FirManglerAdapter import org.jetbrains.kotlin.incremental.components.LookupTracker +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl @@ -103,8 +104,9 @@ internal fun PhaseContext.fir2Ir( "`${irModuleFragment.name}` must be Name.special, since it's required by KlibMetadataModuleDescriptorFactoryImpl.createDescriptorOptionalBuiltIns()" } + @OptIn(ObsoleteDescriptorBasedAPI::class) val usedPackages = buildSet { - components.symbolTable.forEachDeclarationSymbol { + components.symbolTable.descriptorExtension.forEachDeclarationSymbol { val p = it.owner as? IrDeclaration ?: return@forEachDeclarationSymbol val fragment = (p.getPackageFragment() as? IrExternalPackageFragment) ?: return@forEachDeclarationSymbol add(fragment.packageFqName) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt index a62bfdb0160..b984b99d0b1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt @@ -94,7 +94,7 @@ internal interface DescriptorToIrTranslationMixin { } } irConstructor.valueParameters += constructorDescriptor.valueParameters.map { valueParameterDescriptor -> - symbolTable.declareValueParameter( + symbolTable.descriptorExtension.declareValueParameter( SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.DEFINED, valueParameterDescriptor, valueParameterDescriptor.type.toIrType()).also { @@ -127,10 +127,10 @@ internal interface DescriptorToIrTranslationMixin { symbolTable.withScope(irFunction) { irFunction.returnType = functionDescriptor.returnType!!.toIrType() irFunction.valueParameters += functionDescriptor.valueParameters.map { - symbolTable.declareValueParameter(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.DEFINED, it, it.type.toIrType()) + symbolTable.descriptorExtension.declareValueParameter(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.DEFINED, it, it.type.toIrType()) } irFunction.dispatchReceiverParameter = functionDescriptor.dispatchReceiverParameter?.let { - symbolTable.declareValueParameter(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.DEFINED, it, it.type.toIrType()) + symbolTable.descriptorExtension.declareValueParameter(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.DEFINED, it, it.type.toIrType()) } irFunction.generateAnnotations() } @@ -182,4 +182,4 @@ internal fun IrSymbol.findCStructDescriptor(): ClassDescriptor? = internal fun DeclarationDescriptor.findCStructDescriptor(): ClassDescriptor? = parentsWithSelf.filterIsInstance().firstOrNull { it.inheritsFromCStructVar() || it.annotations.hasAnnotation(RuntimeNames.managedType) - } \ No newline at end of file + } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt index d2128b141ac..998bec3eb4b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt @@ -96,7 +96,7 @@ internal class CEnumClassGenerator( ?: error("No `value` property in ${irClass.name}") val irProperty = createProperty(propertyDescriptor) symbolTable.withScope(irProperty) { - irProperty.backingField = symbolTable.declareField( + irProperty.backingField = symbolTable.descriptorExtension.declareField( SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, propertyDescriptor, propertyDescriptor.type.toIrType(), DescriptorVisibilities.PRIVATE ).also { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt index 8824bbb5e10..849fd79d917 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt @@ -148,7 +148,7 @@ internal class CStructVarClassGenerator( val managedValType = managedVal.getter!!.returnType - managedVal.backingField = symbolTable.declareField( + managedVal.backingField = symbolTable.descriptorExtension.declareField( SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,