[IR] Merge IrPrivateSymbolBase and IrPublicSymbolBase hierarchies

^KT-44721 Fixed
diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt
index bd8a400..400e79cc 100644
--- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt
+++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt
@@ -426,7 +426,7 @@
                     if (ownerSymbol is IrClassifierSymbol) {
                         symbolTable.declareGlobalTypeParameter(
                             signature,
-                            symbolFactory = { IrTypeParameterPublicSymbolImpl(signature) }
+                            symbolFactory = { IrTypeParameterSymbolImpl(signature) }
                         ) { symbol ->
                             irFactory.createTypeParameter(
                                 startOffset, endOffset, origin, symbol,
@@ -438,7 +438,7 @@
                     } else {
                         symbolTable.declareScopedTypeParameter(
                             signature,
-                            symbolFactory = { IrTypeParameterPublicSymbolImpl(signature) }
+                            symbolFactory = { IrTypeParameterSymbolImpl(signature) }
                         ) { symbol ->
                             irFactory.createTypeParameter(
                                 startOffset, endOffset, origin, symbol,
diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt
index 19e9095..b16a8da 100644
--- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt
+++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt
@@ -1118,7 +1118,7 @@
         return field.convertWithOffsets { startOffset, endOffset ->
             if (signature != null) {
                 symbolTable.declareField(
-                    signature, symbolFactory = { IrFieldPublicSymbolImpl(signature) }
+                    signature, symbolFactory = { IrFieldSymbolImpl(signature) }
                 ) { symbol ->
                     irFactory.createField(
                         startOffset, endOffset, origin, symbol,
diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt
index e9953f5..7c4bd18 100644
--- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt
+++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt
@@ -700,7 +700,7 @@
             } else null
             (loaded != null) to (loaded ?: components.symbolTable.declareClass(
                 signature,
-                { IrClassPublicSymbolImpl(signature) },
+                { IrClassSymbolImpl(signature) },
                 { symbol ->
                     IrClassBuilder().run {
                         name = Name.identifier(signature.shortName)
@@ -764,7 +764,7 @@
         block: IrClass.() -> Unit = {}
     ): IrClassSymbol = components.symbolTable.declareClass(
         signature,
-        { IrClassPublicSymbolImpl(signature) },
+        { IrClassSymbolImpl(signature) },
         { symbol ->
             IrClassBuilder().run {
                 name = Name.identifier(signature.shortName)
@@ -921,7 +921,7 @@
 
         val irFun4SignatureCalculation = makeWithSymbol(IrSimpleFunctionSymbolImpl())
         val signature = irSignatureBuilder.computeSignature(irFun4SignatureCalculation)
-        return components.symbolTable.declareSimpleFunction(signature, { IrSimpleFunctionPublicSymbolImpl(signature, null) }, ::makeWithSymbol)
+        return components.symbolTable.declareSimpleFunction(signature, { IrSimpleFunctionSymbolImpl(signature, null) }, ::makeWithSymbol)
     }
 
     private fun IrClass.addArrayMembers(elementType: IrType, iteratorType: IrType) {
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 560fb34..60a3b0f 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
@@ -11,14 +11,13 @@
 import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
 import org.jetbrains.kotlin.ir.declarations.*
 import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
-import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
-import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorPublicSymbolImpl
-import org.jetbrains.kotlin.ir.types.classOrNull
-import org.jetbrains.kotlin.ir.util.*
+import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
+import org.jetbrains.kotlin.ir.util.createIrClassFromDescriptor
+import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
+import org.jetbrains.kotlin.ir.util.defaultType
+import org.jetbrains.kotlin.ir.util.withScope
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.psi.KtBlockCodeFragment
-import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset
-import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset
 import org.jetbrains.kotlin.psi2ir.generators.Generator
 import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
 import org.jetbrains.kotlin.psi2ir.generators.createBodyGenerator
@@ -66,7 +65,7 @@
             startOffset = UNDEFINED_OFFSET,
             endOffset = UNDEFINED_OFFSET,
             origin = IrDeclarationOrigin.DEFINED,
-            symbol = IrConstructorPublicSymbolImpl(context.symbolTable.signaturer.composeSignature(irClass.descriptor)!!),
+            symbol = IrConstructorSymbolImpl(context.symbolTable.signaturer.composeSignature(irClass.descriptor)!!),
             Name.special("<init>"),
             irClass.visibility,
             irClass.defaultType,
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPrivateSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPrivateSymbolBase.kt
deleted file mode 100644
index a47fcf3..0000000
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPrivateSymbolBase.kt
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2010-2020 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.symbols.impl
-
-import org.jetbrains.kotlin.descriptors.*
-import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
-import org.jetbrains.kotlin.ir.declarations.*
-import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
-import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
-import org.jetbrains.kotlin.ir.symbols.*
-import org.jetbrains.kotlin.ir.util.IdSignature
-import org.jetbrains.kotlin.ir.util.render
-
-/**
- * The base class for all non-public (wrt linkage) symbols.
- *
- * Its [signature] is always `null`.
- *
- * TODO: Merge with [IrPublicSymbolBase] ([KT-44721](https://youtrack.jetbrains.com/issue/KT-44721))
- */
-@OptIn(ObsoleteDescriptorBasedAPI::class)
-abstract class IrSymbolBase<out Descriptor : DeclarationDescriptor>(
-    private val _descriptor: Descriptor?
-) : IrSymbol {
-    @ObsoleteDescriptorBasedAPI
-    @Suppress("UNCHECKED_CAST")
-    override val descriptor: Descriptor
-        get() = _descriptor ?: (owner as IrDeclaration).toIrBasedDescriptor() as Descriptor
-
-    @ObsoleteDescriptorBasedAPI
-    override val hasDescriptor: Boolean
-        get() = _descriptor != null
-
-    override fun toString(): String {
-        if (isBound) return owner.render()
-        return "Unbound private symbol " +
-                if (_descriptor != null) "${this::class.java.simpleName}: $_descriptor" else super.toString()
-    }
-}
-
-abstract class IrBindableSymbolBase<out Descriptor, Owner>(
-    descriptor: Descriptor?,
-) : IrSymbolBase<Descriptor>(descriptor), IrBindableSymbol<Descriptor, Owner>
-        where Descriptor : DeclarationDescriptor,
-              Owner : IrSymbolOwner {
-
-    init {
-        assert(descriptor == null || isOriginalDescriptor(descriptor)) {
-            "Substituted descriptor $descriptor for ${descriptor!!.original}"
-        }
-        if (descriptor != null) {
-            val containingDeclaration = descriptor.containingDeclaration
-            assert(containingDeclaration == null || isOriginalDescriptor(containingDeclaration)) {
-                "Substituted containing declaration: $containingDeclaration\nfor descriptor: $descriptor"
-            }
-        }
-    }
-
-    private fun isOriginalDescriptor(descriptor: DeclarationDescriptor): Boolean =
-        // TODO fix declaring/referencing value parameters: compute proper original descriptor
-        descriptor is ValueParameterDescriptor && isOriginalDescriptor(descriptor.containingDeclaration) ||
-                descriptor == descriptor.original
-
-    private var _owner: Owner? = null
-    override val owner: Owner
-        get() = _owner ?: throw IllegalStateException("Symbol with ${javaClass.simpleName} is unbound")
-
-    override fun bind(owner: Owner) {
-        if (_owner == null) {
-            _owner = owner
-        } else {
-            throw IllegalStateException("${javaClass.simpleName} is already bound: ${_owner?.render()}")
-        }
-    }
-
-    override val signature: IdSignature?
-        get() = null
-
-    override val isBound: Boolean
-        get() = _owner != null
-
-    override var privateSignature: IdSignature? = null
-}
-
-class IrFileSymbolImpl(descriptor: PackageFragmentDescriptor? = null) :
-    IrBindableSymbolBase<PackageFragmentDescriptor, IrFile>(descriptor),
-    IrFileSymbol
-
-class IrExternalPackageFragmentSymbolImpl(descriptor: PackageFragmentDescriptor? = null) :
-    IrBindableSymbolBase<PackageFragmentDescriptor, IrExternalPackageFragment>(descriptor),
-    IrExternalPackageFragmentSymbol
-
-@OptIn(ObsoleteDescriptorBasedAPI::class)
-class IrAnonymousInitializerSymbolImpl(descriptor: ClassDescriptor? = null) :
-    IrBindableSymbolBase<ClassDescriptor, IrAnonymousInitializer>(descriptor),
-    IrAnonymousInitializerSymbol {
-    constructor(irClassSymbol: IrClassSymbol) : this(irClassSymbol.descriptor)
-}
-
-class IrClassSymbolImpl(descriptor: ClassDescriptor? = null) :
-    IrBindableSymbolBase<ClassDescriptor, IrClass>(descriptor),
-    IrClassSymbol
-
-class IrEnumEntrySymbolImpl(descriptor: ClassDescriptor? = null) :
-    IrBindableSymbolBase<ClassDescriptor, IrEnumEntry>(descriptor),
-    IrEnumEntrySymbol
-
-class IrFieldSymbolImpl(descriptor: PropertyDescriptor? = null) :
-    IrBindableSymbolBase<PropertyDescriptor, IrField>(descriptor),
-    IrFieldSymbol
-
-class IrTypeParameterSymbolImpl(descriptor: TypeParameterDescriptor? = null) :
-    IrBindableSymbolBase<TypeParameterDescriptor, IrTypeParameter>(descriptor),
-    IrTypeParameterSymbol
-
-class IrValueParameterSymbolImpl(descriptor: ParameterDescriptor? = null) :
-    IrBindableSymbolBase<ParameterDescriptor, IrValueParameter>(descriptor),
-    IrValueParameterSymbol
-
-class IrVariableSymbolImpl(descriptor: VariableDescriptor? = null) :
-    IrBindableSymbolBase<VariableDescriptor, IrVariable>(descriptor),
-    IrVariableSymbol
-
-class IrSimpleFunctionSymbolImpl(descriptor: FunctionDescriptor? = null) :
-    IrBindableSymbolBase<FunctionDescriptor, IrSimpleFunction>(descriptor),
-    IrSimpleFunctionSymbol
-
-class IrConstructorSymbolImpl(descriptor: ClassConstructorDescriptor? = null) :
-    IrBindableSymbolBase<ClassConstructorDescriptor, IrConstructor>(descriptor),
-    IrConstructorSymbol
-
-class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor? = null) :
-    IrBindableSymbolBase<FunctionDescriptor, IrReturnableBlock>(descriptor),
-    IrReturnableBlockSymbol
-
-class IrPropertySymbolImpl(descriptor: PropertyDescriptor? = null) :
-    IrBindableSymbolBase<PropertyDescriptor, IrProperty>(descriptor),
-    IrPropertySymbol
-
-class IrLocalDelegatedPropertySymbolImpl(descriptor: VariableDescriptorWithAccessors? = null) :
-    IrBindableSymbolBase<VariableDescriptorWithAccessors, IrLocalDelegatedProperty>(descriptor),
-    IrLocalDelegatedPropertySymbol
-
-class IrTypeAliasSymbolImpl(descriptor: TypeAliasDescriptor? = null) :
-    IrBindableSymbolBase<TypeAliasDescriptor, IrTypeAlias>(descriptor),
-    IrTypeAliasSymbol
-
-class IrScriptSymbolImpl(descriptor: ScriptDescriptor? = null) :
-    IrScriptSymbol, IrBindableSymbolBase<ScriptDescriptor, IrScript>(descriptor)
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt
deleted file mode 100644
index 7bbbca7..0000000
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2010-2019 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.symbols.impl
-
-import org.jetbrains.kotlin.descriptors.*
-import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
-import org.jetbrains.kotlin.ir.declarations.*
-import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
-import org.jetbrains.kotlin.ir.symbols.*
-import org.jetbrains.kotlin.ir.util.IdSignature
-import org.jetbrains.kotlin.ir.util.render
-
-/**
- * The base class for all public (wrt linkage) symbols.
- *
- * Its [signature] is never `null`.
- *
- * TODO: Merge with [IrSymbolBase] ([KT-44721](https://youtrack.jetbrains.com/issue/KT-44721))
- */
-abstract class IrPublicSymbolBase<out Descriptor : DeclarationDescriptor>(
-    override val signature: IdSignature,
-    private val _descriptor: Descriptor?
-) : IrSymbol {
-    @ObsoleteDescriptorBasedAPI
-    @Suppress("UNCHECKED_CAST")
-    override val descriptor: Descriptor
-        get() = _descriptor ?: (owner as IrDeclaration).toIrBasedDescriptor() as Descriptor
-
-    @ObsoleteDescriptorBasedAPI
-    override val hasDescriptor: Boolean
-        get() = _descriptor != null
-
-    override fun toString(): String {
-        if (isBound) return owner.render()
-        return "Unbound public symbol ${this::class.java.simpleName}: $signature"
-    }
-}
-
-abstract class IrBindablePublicSymbolBase<out Descriptor, Owner>(
-    sig: IdSignature,
-    descriptor: Descriptor?,
-) : IrPublicSymbolBase<Descriptor>(sig, descriptor), IrBindableSymbol<Descriptor, Owner>
-        where Descriptor : DeclarationDescriptor,
-              Owner : IrSymbolOwner {
-
-    init {
-        assert(descriptor == null || isOriginalDescriptor(descriptor)) {
-            "Substituted descriptor $descriptor for ${descriptor!!.original}"
-        }
-//        assert(sig.isPubliclyVisible)
-    }
-
-    private fun isOriginalDescriptor(descriptor: DeclarationDescriptor): Boolean =
-        // TODO fix declaring/referencing value parameters: compute proper original descriptor
-        descriptor is ValueParameterDescriptor && isOriginalDescriptor(descriptor.containingDeclaration) ||
-                descriptor == descriptor.original
-
-    private var _owner: Owner? = null
-    override val owner: Owner
-        get() = _owner ?: throw IllegalStateException("Symbol for $signature is unbound")
-
-    override fun bind(owner: Owner) {
-        if (_owner == null) {
-            _owner = owner
-        } else {
-            throw IllegalStateException("${javaClass.simpleName} for $signature is already bound: ${_owner?.render()}")
-        }
-    }
-
-    override val isBound: Boolean
-        get() = _owner != null
-
-    override var privateSignature: IdSignature? = null
-}
-
-class IrClassPublicSymbolImpl(sig: IdSignature, descriptor: ClassDescriptor? = null) :
-    IrBindablePublicSymbolBase<ClassDescriptor, IrClass>(sig, descriptor),
-    IrClassSymbol
-
-class IrEnumEntryPublicSymbolImpl(sig: IdSignature, descriptor: ClassDescriptor? = null) :
-    IrBindablePublicSymbolBase<ClassDescriptor, IrEnumEntry>(sig, descriptor),
-    IrEnumEntrySymbol
-
-class IrSimpleFunctionPublicSymbolImpl(sig: IdSignature, descriptor: FunctionDescriptor? = null) :
-    IrBindablePublicSymbolBase<FunctionDescriptor, IrSimpleFunction>(sig, descriptor),
-    IrSimpleFunctionSymbol
-
-class IrConstructorPublicSymbolImpl(sig: IdSignature, descriptor: ClassConstructorDescriptor? = null) :
-    IrBindablePublicSymbolBase<ClassConstructorDescriptor, IrConstructor>(sig, descriptor),
-    IrConstructorSymbol
-
-class IrPropertyPublicSymbolImpl(sig: IdSignature, descriptor: PropertyDescriptor? = null) :
-    IrBindablePublicSymbolBase<PropertyDescriptor, IrProperty>(sig, descriptor),
-    IrPropertySymbol
-
-class IrTypeAliasPublicSymbolImpl(sig: IdSignature, descriptor: TypeAliasDescriptor? = null) :
-    IrBindablePublicSymbolBase<TypeAliasDescriptor, IrTypeAlias>(sig, descriptor),
-    IrTypeAliasSymbol
-
-class IrFieldPublicSymbolImpl(sig: IdSignature, descriptor: PropertyDescriptor? = null) :
-    IrBindablePublicSymbolBase<PropertyDescriptor, IrField>(sig, descriptor),
-    IrFieldSymbol
-
-class IrTypeParameterPublicSymbolImpl(sig: IdSignature, descriptor: TypeParameterDescriptor? = null) :
-    IrBindablePublicSymbolBase<TypeParameterDescriptor, IrTypeParameter>(sig, descriptor),
-    IrTypeParameterSymbol
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt
new file mode 100644
index 0000000..4ac7a31
--- /dev/null
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt
@@ -0,0 +1,175 @@
+/*
+ * 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.symbols.impl
+
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
+import org.jetbrains.kotlin.ir.declarations.*
+import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
+import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
+import org.jetbrains.kotlin.ir.symbols.*
+import org.jetbrains.kotlin.ir.util.IdSignature
+import org.jetbrains.kotlin.ir.util.render
+
+abstract class IrSymbolBase<out Descriptor : DeclarationDescriptor>(
+    final override val signature: IdSignature?,
+    private val _descriptor: Descriptor?
+) : IrSymbol {
+    @ObsoleteDescriptorBasedAPI
+    @Suppress("UNCHECKED_CAST")
+    override val descriptor: Descriptor
+        get() = _descriptor ?: (owner as IrDeclaration).toIrBasedDescriptor() as Descriptor
+
+    @ObsoleteDescriptorBasedAPI
+    override val hasDescriptor: Boolean
+        get() = _descriptor != null
+
+    override fun toString(): String {
+        if (isBound) return owner.render()
+
+        return if (signature == null) {
+            "Unbound private symbol " +
+                    if (_descriptor != null) "${this::class.java.simpleName}: $_descriptor" else super.toString()
+        } else {
+            "Unbound public symbol ${this::class.java.simpleName}: $signature"
+        }
+    }
+}
+
+abstract class IrBindableSymbolBase<out Descriptor, Owner>(
+    signature: IdSignature?,
+    descriptor: Descriptor?,
+) : IrSymbolBase<Descriptor>(signature, descriptor), IrBindableSymbol<Descriptor, Owner>
+        where Descriptor : DeclarationDescriptor,
+              Owner : IrSymbolOwner {
+
+    init {
+        assert(descriptor == null || isOriginalDescriptor(descriptor)) {
+            "Substituted descriptor $descriptor for ${descriptor!!.original}"
+        }
+//        assert(sig.isPubliclyVisible)
+        if (descriptor != null && signature == null) {
+            val containingDeclaration = descriptor.containingDeclaration
+            assert(containingDeclaration == null || isOriginalDescriptor(containingDeclaration)) {
+                "Substituted containing declaration: $containingDeclaration\nfor descriptor: $descriptor"
+            }
+        }
+    }
+
+    private fun isOriginalDescriptor(descriptor: DeclarationDescriptor): Boolean =
+        // TODO fix declaring/referencing value parameters: compute proper original descriptor
+        descriptor is ValueParameterDescriptor && isOriginalDescriptor(descriptor.containingDeclaration) ||
+                descriptor == descriptor.original
+
+    private var _owner: Owner? = null
+    override val owner: Owner
+        get() = _owner ?: throw IllegalStateException("Symbol for ${signature ?: javaClass.simpleName} is unbound")
+
+    override fun bind(owner: Owner) {
+        _owner?.let { existingOwner ->
+            throw IllegalStateException(
+                buildString {
+                    append(javaClass.simpleName)
+                    signature?.let {
+                        append(" for ")
+                        append(it)
+                    }
+                    append(" is already bound: ")
+                    append(existingOwner.render())
+                },
+            )
+        }
+        _owner = owner
+    }
+
+    override val isBound: Boolean
+        get() = _owner != null
+
+    override var privateSignature: IdSignature? = null
+}
+
+class IrFileSymbolImpl(descriptor: PackageFragmentDescriptor? = null) :
+    IrBindableSymbolBase<PackageFragmentDescriptor, IrFile>(null, descriptor),
+    IrFileSymbol
+
+class IrExternalPackageFragmentSymbolImpl(descriptor: PackageFragmentDescriptor? = null) :
+    IrBindableSymbolBase<PackageFragmentDescriptor, IrExternalPackageFragment>(null, descriptor),
+    IrExternalPackageFragmentSymbol
+
+@OptIn(ObsoleteDescriptorBasedAPI::class)
+class IrAnonymousInitializerSymbolImpl(descriptor: ClassDescriptor? = null) :
+    IrBindableSymbolBase<ClassDescriptor, IrAnonymousInitializer>(null, descriptor),
+    IrAnonymousInitializerSymbol {
+    constructor(irClassSymbol: IrClassSymbol) : this(irClassSymbol.descriptor)
+}
+
+class IrClassSymbolImpl(sig: IdSignature?, descriptor: ClassDescriptor? = null) :
+    IrBindableSymbolBase<ClassDescriptor, IrClass>(sig, descriptor),
+    IrClassSymbol {
+    constructor(descriptor: ClassDescriptor? = null) : this(null, descriptor)
+}
+
+class IrEnumEntrySymbolImpl(sig: IdSignature?, descriptor: ClassDescriptor? = null) :
+    IrBindableSymbolBase<ClassDescriptor, IrEnumEntry>(sig, descriptor),
+    IrEnumEntrySymbol {
+    constructor(descriptor: ClassDescriptor? = null) : this(null, descriptor)
+}
+
+class IrFieldSymbolImpl(sig: IdSignature?, descriptor: PropertyDescriptor? = null) :
+    IrBindableSymbolBase<PropertyDescriptor, IrField>(sig, descriptor),
+    IrFieldSymbol {
+    constructor(descriptor: PropertyDescriptor? = null) : this(null, descriptor)
+}
+
+class IrTypeParameterSymbolImpl(sig: IdSignature?, descriptor: TypeParameterDescriptor? = null) :
+    IrBindableSymbolBase<TypeParameterDescriptor, IrTypeParameter>(sig, descriptor),
+    IrTypeParameterSymbol {
+    constructor(descriptor: TypeParameterDescriptor? = null) : this(null, descriptor)
+}
+
+class IrValueParameterSymbolImpl(descriptor: ParameterDescriptor? = null) :
+    IrBindableSymbolBase<ParameterDescriptor, IrValueParameter>(null, descriptor),
+    IrValueParameterSymbol
+
+class IrVariableSymbolImpl(descriptor: VariableDescriptor? = null) :
+    IrBindableSymbolBase<VariableDescriptor, IrVariable>(null, descriptor),
+    IrVariableSymbol
+
+class IrSimpleFunctionSymbolImpl(sig: IdSignature?, descriptor: FunctionDescriptor? = null) :
+    IrBindableSymbolBase<FunctionDescriptor, IrSimpleFunction>(sig, descriptor),
+    IrSimpleFunctionSymbol {
+    constructor(descriptor: FunctionDescriptor? = null) : this(null, descriptor)
+}
+
+class IrConstructorSymbolImpl(sig: IdSignature?, descriptor: ClassConstructorDescriptor? = null) :
+    IrBindableSymbolBase<ClassConstructorDescriptor, IrConstructor>(sig, descriptor),
+    IrConstructorSymbol {
+    constructor(descriptor: ClassConstructorDescriptor? = null) : this(null, descriptor)
+}
+
+class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor? = null) :
+    IrBindableSymbolBase<FunctionDescriptor, IrReturnableBlock>(null, descriptor),
+    IrReturnableBlockSymbol
+
+class IrPropertySymbolImpl(sig: IdSignature?, descriptor: PropertyDescriptor? = null) :
+    IrBindableSymbolBase<PropertyDescriptor, IrProperty>(sig, descriptor),
+    IrPropertySymbol {
+    constructor(descriptor: PropertyDescriptor? = null) : this(null, descriptor)
+}
+
+class IrLocalDelegatedPropertySymbolImpl(descriptor: VariableDescriptorWithAccessors? = null) :
+    IrBindableSymbolBase<VariableDescriptorWithAccessors, IrLocalDelegatedProperty>(null, descriptor),
+    IrLocalDelegatedPropertySymbol
+
+class IrTypeAliasSymbolImpl(sig: IdSignature?, descriptor: TypeAliasDescriptor? = null) :
+    IrBindableSymbolBase<TypeAliasDescriptor, IrTypeAlias>(sig, descriptor),
+    IrTypeAliasSymbol {
+    constructor(descriptor: TypeAliasDescriptor? = null) : this(null, descriptor)
+}
+
+class IrScriptSymbolImpl(descriptor: ScriptDescriptor? = null) :
+    IrBindableSymbolBase<ScriptDescriptor, IrScript>(null, descriptor),
+    IrScriptSymbol
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt
index 315e56e..6bdcd47 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt
@@ -14,7 +14,7 @@
 import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
 import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
 import org.jetbrains.kotlin.ir.symbols.IrSymbol
-import org.jetbrains.kotlin.ir.symbols.impl.IrClassPublicSymbolImpl
+import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
 import org.jetbrains.kotlin.name.ClassId
 import org.jetbrains.kotlin.name.FqName
 import org.jetbrains.kotlin.name.Name
@@ -116,7 +116,7 @@
     }
 
 fun IrSymbol.hasEqualFqName(fqName: FqName): Boolean {
-    return this is IrClassPublicSymbolImpl && with(signature as? IdSignature.CommonSignature ?: return false) {
+    return this is IrClassSymbolImpl && with(signature as? IdSignature.CommonSignature ?: return false) {
         FqName("$packageFqName.$declarationFqName") == fqName
     }
 }
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 5a15c88..a31d77f 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
@@ -264,7 +264,7 @@
         // `descriptor`, a symbol created for `descriptor` will be bound, not the built-in symbol which should be. If `generateClassStub` is
         // called twice for such a `descriptor`, an exception will occur because `descriptor`'s symbol will already have been bound.
         //
-        // Note as well that not all symbols have descriptors. For example, `irClassSymbol` might be an `IrClassPublicSymbolImpl` without a
+        // Note as well that not all symbols have descriptors. For example, `irClassSymbol` might be an `IrClassSymbolImpl` without a
         // descriptor. For such symbols, the `descriptor` argument needs to be used.
         val targetDescriptor = if (irClassSymbol.hasDescriptor) irClassSymbol.descriptor else descriptor
         with(targetDescriptor) {
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopySymbolRemapperPreservingSignatures.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopySymbolRemapperPreservingSignatures.kt
index ba8aa38..ed60e11 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopySymbolRemapperPreservingSignatures.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopySymbolRemapperPreservingSignatures.kt
@@ -12,42 +12,42 @@
 open class DeepCopySymbolRemapperPreservingSignatures : DeepCopySymbolRemapper() {
     override fun visitClass(declaration: IrClass) {
         remapSymbol(classes, declaration) { symbol ->
-            symbol.signature?.let { sig -> IrClassPublicSymbolImpl(sig) } ?: IrClassSymbolImpl()
+            IrClassSymbolImpl(symbol.signature)
         }
         declaration.acceptChildrenVoid(this)
     }
 
     override fun visitConstructor(declaration: IrConstructor) {
         remapSymbol(constructors, declaration) { symbol ->
-            symbol.signature?.let { sig -> IrConstructorPublicSymbolImpl(sig) } ?: IrConstructorSymbolImpl()
+            IrConstructorSymbolImpl(symbol.signature)
         }
         declaration.acceptChildrenVoid(this)
     }
 
     override fun visitEnumEntry(declaration: IrEnumEntry) {
         remapSymbol(enumEntries, declaration) { symbol ->
-            symbol.signature?.let { sig -> IrEnumEntryPublicSymbolImpl(sig) } ?: IrEnumEntrySymbolImpl()
+            IrEnumEntrySymbolImpl(symbol.signature)
         }
         declaration.acceptChildrenVoid(this)
     }
 
     override fun visitSimpleFunction(declaration: IrSimpleFunction) {
         remapSymbol(functions, declaration) { symbol ->
-            symbol.signature?.let { sig -> IrSimpleFunctionPublicSymbolImpl(sig) } ?: IrSimpleFunctionSymbolImpl()
+            IrSimpleFunctionSymbolImpl(symbol.signature)
         }
         declaration.acceptChildrenVoid(this)
     }
 
     override fun visitProperty(declaration: IrProperty) {
         remapSymbol(properties, declaration) { symbol ->
-            symbol.signature?.let { sig -> IrPropertyPublicSymbolImpl(sig) } ?: IrPropertySymbolImpl()
+            IrPropertySymbolImpl(symbol.signature)
         }
         declaration.acceptChildrenVoid(this)
     }
 
     override fun visitTypeAlias(declaration: IrTypeAlias) {
         remapSymbol(typeAliases, declaration) { symbol ->
-            symbol.signature?.let { sig -> IrTypeAliasPublicSymbolImpl(sig) } ?: IrTypeAliasSymbolImpl()
+            IrTypeAliasSymbolImpl(symbol.signature)
         }
         declaration.acceptChildrenVoid(this)
     }
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 eae1cab..326e218 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
@@ -496,7 +496,7 @@
         scriptSymbolTable.referenced(descriptor) { IrScriptSymbolImpl(descriptor) }
 
     private fun createClassSymbol(descriptor: ClassDescriptor, signature: IdSignature?): IrClassSymbol =
-        signature?.let { IrClassPublicSymbolImpl(it, descriptor) } ?: IrClassSymbolImpl(descriptor)
+        IrClassSymbolImpl(signature, descriptor)
 
     @ObsoleteDescriptorBasedAPI
     fun declareClass(
@@ -536,7 +536,7 @@
     fun declareClassFromLinker(descriptor: ClassDescriptor, signature: IdSignature, factory: (IrClassSymbol) -> IrClass): IrClass {
         return classSymbolTable.run {
             if (signature.isPubliclyVisible) {
-                declare(signature, descriptor, { IrClassPublicSymbolImpl(signature, descriptor) }, factory)
+                declare(signature, descriptor, { IrClassSymbolImpl(signature, descriptor) }, factory)
             } else {
                 declare(descriptor, { IrClassSymbolImpl(descriptor) }, factory)
             }
@@ -566,7 +566,7 @@
 
     override fun referenceClass(signature: IdSignature): IrClassSymbol =
         classSymbolTable.run {
-            if (signature.isPubliclyVisible) referenced(signature) { IrClassPublicSymbolImpl(signature) }
+            if (signature.isPubliclyVisible) referenced(signature) { IrClassSymbolImpl(signature) }
             else IrClassSymbolImpl().also {
                 it.privateSignature = signature
             }
@@ -575,7 +575,7 @@
     val unboundClasses: Set<IrClassSymbol> get() = classSymbolTable.unboundSymbols
 
     private fun createConstructorSymbol(descriptor: ClassConstructorDescriptor, signature: IdSignature?): IrConstructorSymbol =
-        signature?.let { IrConstructorPublicSymbolImpl(it, descriptor) } ?: IrConstructorSymbolImpl(descriptor)
+        IrConstructorSymbolImpl(signature, descriptor)
 
     @ObsoleteDescriptorBasedAPI
     fun declareConstructor(
@@ -632,7 +632,7 @@
     ): IrConstructor {
         return constructorSymbolTable.run {
             if (signature.isPubliclyVisible) {
-                declare(signature, descriptor, { IrConstructorPublicSymbolImpl(signature, descriptor) }, constructorFactory)
+                declare(signature, descriptor, { IrConstructorSymbolImpl(signature, descriptor) }, constructorFactory)
             } else {
                 declare(descriptor, { IrConstructorSymbolImpl(descriptor) }, constructorFactory)
             }
@@ -641,14 +641,14 @@
 
     override fun referenceConstructor(signature: IdSignature): IrConstructorSymbol =
         constructorSymbolTable.run {
-            if (signature.isPubliclyVisible) referenced(signature) { IrConstructorPublicSymbolImpl(signature) }
+            if (signature.isPubliclyVisible) referenced(signature) { IrConstructorSymbolImpl(signature) }
             else IrConstructorSymbolImpl()
         }
 
     val unboundConstructors: Set<IrConstructorSymbol> get() = constructorSymbolTable.unboundSymbols
 
     private fun createEnumEntrySymbol(descriptor: ClassDescriptor, signature: IdSignature?): IrEnumEntrySymbol =
-        signature?.let { IrEnumEntryPublicSymbolImpl(it, descriptor) } ?: IrEnumEntrySymbolImpl(descriptor)
+        IrEnumEntrySymbolImpl(signature, descriptor)
 
     @ObsoleteDescriptorBasedAPI
     fun declareEnumEntry(
@@ -683,7 +683,7 @@
     ): IrEnumEntry {
         return enumEntrySymbolTable.run {
             if (signature.isPubliclyVisible) {
-                declare(signature, descriptor, { IrEnumEntryPublicSymbolImpl(signature, descriptor) }, factory)
+                declare(signature, descriptor, { IrEnumEntrySymbolImpl(signature, descriptor) }, factory)
             } else {
                 declare(descriptor, { IrEnumEntrySymbolImpl(descriptor) }, factory)
             }
@@ -696,14 +696,14 @@
 
     override fun referenceEnumEntry(signature: IdSignature) =
         enumEntrySymbolTable.run {
-            if (signature.isPubliclyVisible) referenced(signature) { IrEnumEntryPublicSymbolImpl(signature) }
+            if (signature.isPubliclyVisible) referenced(signature) { IrEnumEntrySymbolImpl(signature) }
             else IrEnumEntrySymbolImpl()
         }
 
     val unboundEnumEntries: Set<IrEnumEntrySymbol> get() = enumEntrySymbolTable.unboundSymbols
 
     private fun createFieldSymbol(descriptor: PropertyDescriptor, signature: IdSignature?): IrFieldSymbol =
-        signature?.let { IrFieldPublicSymbolImpl(it, descriptor) } ?: IrFieldSymbolImpl(descriptor)
+        IrFieldSymbolImpl(signature, descriptor)
 
     @OptIn(ObsoleteDescriptorBasedAPI::class)
     fun declareField(
@@ -765,7 +765,7 @@
     override fun referenceField(signature: IdSignature): IrFieldSymbol =
         fieldSymbolTable.run {
             if (signature.isPubliclyVisible) {
-                referenced(signature) { IrFieldPublicSymbolImpl(signature) }
+                referenced(signature) { IrFieldSymbolImpl(signature) }
             } else IrFieldSymbolImpl()
         }
 
@@ -780,7 +780,7 @@
         propertyTable.getOrPut(descriptor, generate)
 
     private fun createPropertySymbol(descriptor: PropertyDescriptor, signature: IdSignature?): IrPropertySymbol =
-        signature?.let { IrPropertyPublicSymbolImpl(it, descriptor) } ?: IrPropertySymbolImpl(descriptor)
+        IrPropertySymbolImpl(signature, descriptor)
 
     @ObsoleteDescriptorBasedAPI
     fun declareProperty(
@@ -836,7 +836,7 @@
     ): IrProperty {
         return propertySymbolTable.run {
             if (signature.isPubliclyVisible) {
-                declare(signature, descriptor, { IrPropertyPublicSymbolImpl(signature, descriptor) }, factory)
+                declare(signature, descriptor, { IrPropertySymbolImpl(signature, descriptor) }, factory)
             } else {
                 declare(descriptor, { IrPropertySymbolImpl(descriptor) }, factory)
             }
@@ -856,14 +856,14 @@
 
     override fun referenceProperty(signature: IdSignature): IrPropertySymbol =
         propertySymbolTable.run {
-            if (signature.isPubliclyVisible) referenced(signature) { IrPropertyPublicSymbolImpl(signature) }
+            if (signature.isPubliclyVisible) referenced(signature) { IrPropertySymbolImpl(signature) }
             else IrPropertySymbolImpl()
         }
 
     val unboundProperties: Set<IrPropertySymbol> get() = propertySymbolTable.unboundSymbols
 
     private fun createTypeAliasSymbol(descriptor: TypeAliasDescriptor, signature: IdSignature?): IrTypeAliasSymbol =
-        signature?.let { IrTypeAliasPublicSymbolImpl(it, descriptor) } ?: IrTypeAliasSymbolImpl(descriptor)
+        IrTypeAliasSymbolImpl(signature, descriptor)
 
     @ObsoleteDescriptorBasedAPI
     override fun referenceTypeAlias(descriptor: TypeAliasDescriptor): IrTypeAliasSymbol =
@@ -871,7 +871,7 @@
 
     override fun referenceTypeAlias(signature: IdSignature) =
         typeAliasSymbolTable.run {
-            if (signature.isPubliclyVisible) referenced(signature) { IrTypeAliasPublicSymbolImpl(signature) }
+            if (signature.isPubliclyVisible) referenced(signature) { IrTypeAliasSymbolImpl(signature) }
             else IrTypeAliasSymbolImpl()
         }
 
@@ -894,7 +894,7 @@
     val unboundTypeAliases: Set<IrTypeAliasSymbol> get() = typeAliasSymbolTable.unboundSymbols
 
     private fun createSimpleFunctionSymbol(descriptor: FunctionDescriptor, signature: IdSignature?): IrSimpleFunctionSymbol =
-        signature?.let { IrSimpleFunctionPublicSymbolImpl(it, descriptor) } ?: IrSimpleFunctionSymbolImpl(descriptor)
+        IrSimpleFunctionSymbolImpl(signature, descriptor)
 
     @ObsoleteDescriptorBasedAPI
     fun declareSimpleFunction(
@@ -937,7 +937,7 @@
     ): IrSimpleFunction {
         return simpleFunctionSymbolTable.run {
             if (signature.isPubliclyVisible) {
-                declare(signature, descriptor, { IrSimpleFunctionPublicSymbolImpl(signature, descriptor) }, functionFactory)
+                declare(signature, descriptor, { IrSimpleFunctionSymbolImpl(signature, descriptor) }, functionFactory)
             } else {
                 declare(descriptor!!, { IrSimpleFunctionSymbolImpl(descriptor) }, functionFactory)
             }
@@ -957,7 +957,7 @@
 
     override fun referenceSimpleFunction(signature: IdSignature): IrSimpleFunctionSymbol {
         return simpleFunctionSymbolTable.run {
-            if (signature.isPubliclyVisible) referenced(signature) { IrSimpleFunctionPublicSymbolImpl(signature) }
+            if (signature.isPubliclyVisible) referenced(signature) { IrSimpleFunctionSymbolImpl(signature) }
             else IrSimpleFunctionSymbolImpl().also {
                 it.privateSignature = signature
             }
@@ -971,7 +971,7 @@
     val unboundSimpleFunctions: Set<IrSimpleFunctionSymbol> get() = simpleFunctionSymbolTable.unboundSymbols
 
     private fun createTypeParameterSymbol(descriptor: TypeParameterDescriptor, signature: IdSignature?): IrTypeParameterSymbol =
-        signature?.let { IrTypeParameterPublicSymbolImpl(it, descriptor) } ?: IrTypeParameterSymbolImpl(descriptor)
+        IrTypeParameterSymbolImpl(signature, descriptor)
 
     @ObsoleteDescriptorBasedAPI
     fun declareGlobalTypeParameter(
@@ -1076,7 +1076,7 @@
 
     override fun referenceTypeParameter(signature: IdSignature): IrTypeParameterSymbol =
         globalTypeParameterSymbolTable.referenced(signature) {
-            if (signature.isPubliclyVisible) IrTypeParameterPublicSymbolImpl(signature) else IrTypeParameterSymbolImpl()
+            IrTypeParameterSymbolImpl(signature.takeIf { it.isPubliclyVisible })
         }
 
     @ObsoleteDescriptorBasedAPI
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrDeclarationDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrDeclarationDeserializer.kt
index 5228cb4..a46c359 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrDeclarationDeserializer.kt
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrDeclarationDeserializer.kt
@@ -25,7 +25,6 @@
 import org.jetbrains.kotlin.ir.expressions.*
 import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
 import org.jetbrains.kotlin.ir.symbols.*
-import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase
 import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
 import org.jetbrains.kotlin.ir.types.*
 import org.jetbrains.kotlin.ir.types.impl.*
@@ -813,8 +812,7 @@
             // Don't consider IR_FIELDS here.
             else -> return false
         }
-        if (symbol !is IrPublicSymbolBase<*>) return false
-        if (!symbol.signature.isPubliclyVisible) return false
+        if (symbol.signature?.isPubliclyVisible != true) return false
 
         return when (proto.declaratorCase!!) {
             IR_FUNCTION -> FunctionFlags.decode(proto.irFunction.base.base.flags).isFakeOverride
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt
index 648bd84..0acb845 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt
@@ -428,7 +428,7 @@
     }
 
     private fun IrClassSymbol.isInterop(): Boolean {
-        if (this is IrPublicSymbolBase<*> && this.signature.isInteropSignature()) return true
+        if (this.signature?.isInteropSignature() == true) return true
 
         // K2 doesn't properly put signatures into such symbols yet, workaround:
         return this.isBound && this.owner is Fir2IrLazyClass && this.descriptor.isFromInteropLibrary()