IR: make descriptor optional in IrSymbol

This commit is contained in:
Georgy Bronnikov
2020-11-27 17:31:03 +03:00
parent aaa3f2e2c1
commit 989d4350b1
4 changed files with 48 additions and 17 deletions
@@ -14,9 +14,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -34,7 +32,8 @@ import org.jetbrains.kotlin.types.*
/* Descriptors that serve purely as a view into IR structures. /* Descriptors that serve purely as a view into IR structures.
Created each time at the borderline between IR-based and descriptor-based code (such as inliner). Created each time at the borderline between IR-based and descriptor-based code (such as inliner).
Compared to WrappedDescriptors, no method calls ever return true descriptors. Compared to WrappedDescriptors, no method calls ever return true descriptors, except when
unbound symbols are encountered (see `Ir...Symbol.toIrBasedDescriptorIfPossible()`).
*/ */
abstract class IrBasedDeclarationDescriptor<T : IrDeclaration>(val owner: T) : DeclarationDescriptor { abstract class IrBasedDeclarationDescriptor<T : IrDeclaration>(val owner: T) : DeclarationDescriptor {
@@ -108,6 +107,7 @@ fun IrDeclaration.toIrBasedDescriptor(): DeclarationDescriptor = when (this) {
is IrLocalDelegatedProperty -> toIrBasedDescriptor() is IrLocalDelegatedProperty -> toIrBasedDescriptor()
is IrFunction -> toIrBasedDescriptor() is IrFunction -> toIrBasedDescriptor()
is IrClass -> toIrBasedDescriptor() is IrClass -> toIrBasedDescriptor()
is IrAnonymousInitializer -> parentAsClass.toIrBasedDescriptor()
is IrEnumEntry -> toIrBasedDescriptor() is IrEnumEntry -> toIrBasedDescriptor()
is IrProperty -> toIrBasedDescriptor() is IrProperty -> toIrBasedDescriptor()
is IrField -> toIrBasedDescriptor() is IrField -> toIrBasedDescriptor()
@@ -1060,9 +1060,9 @@ private fun makeKotlinType(
hasQuestionMark: Boolean hasQuestionMark: Boolean
): SimpleType = ): SimpleType =
when (classifier) { when (classifier) {
is IrTypeParameterSymbol -> classifier.owner.toIrBasedDescriptor().defaultType is IrTypeParameterSymbol -> classifier.toIrBasedDescriptorIfPossible().defaultType
is IrClassSymbol -> { is IrClassSymbol -> {
val classDescriptor = classifier.owner.toIrBasedDescriptor() val classDescriptor = classifier.toIrBasedDescriptorIfPossible()
val kotlinTypeArguments = arguments.mapIndexed { index, it -> val kotlinTypeArguments = arguments.mapIndexed { index, it ->
when (it) { when (it) {
is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toIrBasedKotlinType()) is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toIrBasedKotlinType())
@@ -1094,3 +1094,20 @@ private fun makeKotlinType(
} }
else -> error("unknown classifier kind $classifier") else -> error("unknown classifier kind $classifier")
} }
/* When IR-based descriptors are used from Psi2Ir, symbols may be unbound, thus we may need to resort to real descriptors. */
@OptIn(ObsoleteDescriptorBasedAPI::class)
private fun IrClassSymbol.toIrBasedDescriptorIfPossible(): ClassDescriptor =
if (isBound) owner.toIrBasedDescriptor() else descriptor
@OptIn(ObsoleteDescriptorBasedAPI::class)
private fun IrTypeParameterSymbol.toIrBasedDescriptorIfPossible(): TypeParameterDescriptor =
if (isBound) owner.toIrBasedDescriptor() else descriptor
@OptIn(ObsoleteDescriptorBasedAPI::class)
private fun IrSimpleFunctionSymbol.toIrBasedDescriptorIfPossible(): FunctionDescriptor =
if (isBound) owner.toIrBasedDescriptor() else descriptor
@OptIn(ObsoleteDescriptorBasedAPI::class)
private fun IrPropertySymbol.toIrBasedDescriptorIfPossible(): PropertyDescriptor =
if (isBound) owner.toIrBasedDescriptor() else descriptor
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor
import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
@@ -27,9 +28,15 @@ import org.jetbrains.kotlin.ir.util.render
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class IrSymbolBase<out D : DeclarationDescriptor>( abstract class IrSymbolBase<out D : DeclarationDescriptor>(
private val _descriptor: D
) : IrSymbol {
@ObsoleteDescriptorBasedAPI @ObsoleteDescriptorBasedAPI
override val descriptor: D override val descriptor: D
) : IrSymbol { get() = if (isBound && _descriptor is WrappedDeclarationDescriptor<*>)
(owner as IrDeclaration).toIrBasedDescriptor() as D
else
_descriptor
override fun toString(): String { override fun toString(): String {
if (isBound) return owner.render() if (isBound) return owner.render()
return "Unbound private symbol ${super.toString()}" return "Unbound private symbol ${super.toString()}"
@@ -9,15 +9,22 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor
import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
abstract class IrPublicSymbolBase<out D : DeclarationDescriptor> @OptIn(ObsoleteDescriptorBasedAPI::class) constructor( abstract class IrPublicSymbolBase<out D : DeclarationDescriptor> @OptIn(ObsoleteDescriptorBasedAPI::class) constructor(
@ObsoleteDescriptorBasedAPI private val _descriptor: D,
override val descriptor: D,
override val signature: IdSignature override val signature: IdSignature
) : IrSymbol { ) : IrSymbol {
@ObsoleteDescriptorBasedAPI
override val descriptor: D
get() = if (isBound && _descriptor is WrappedDeclarationDescriptor<*>)
(owner as IrDeclaration).toIrBasedDescriptor() as D
else
_descriptor
override fun toString(): String { override fun toString(): String {
if (isBound) return owner.render() if (isBound) return owner.render()
return "Unbound public symbol for $signature" return "Unbound public symbol for $signature"
@@ -58,34 +58,34 @@ object WrappedDescriptorPatcher : IrElementVisitorVoid {
} }
override fun visitClass(declaration: IrClass) { override fun visitClass(declaration: IrClass) {
(declaration.descriptor as WrappedClassDescriptor).bind(declaration) (declaration.descriptor as? WrappedClassDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
override fun visitConstructor(declaration: IrConstructor) { override fun visitConstructor(declaration: IrConstructor) {
(declaration.descriptor as WrappedClassConstructorDescriptor).bind(declaration) (declaration.descriptor as? WrappedClassConstructorDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
override fun visitEnumEntry(declaration: IrEnumEntry) { override fun visitEnumEntry(declaration: IrEnumEntry) {
(declaration.descriptor as WrappedClassDescriptor).bind( (declaration.descriptor as? WrappedClassDescriptor)?.bind(
declaration.correspondingClass ?: declaration.parentAsClass declaration.correspondingClass ?: declaration.parentAsClass
) )
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
override fun visitField(declaration: IrField) { override fun visitField(declaration: IrField) {
(declaration.descriptor as WrappedFieldDescriptor).bind(declaration) (declaration.descriptor as? WrappedFieldDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
override fun visitProperty(declaration: IrProperty) { override fun visitProperty(declaration: IrProperty) {
(declaration.descriptor as WrappedPropertyDescriptor).bind(declaration) (declaration.descriptor as? WrappedPropertyDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
override fun visitFunction(declaration: IrFunction) { override fun visitFunction(declaration: IrFunction) {
(declaration.descriptor as WrappedSimpleFunctionDescriptor).bind(declaration as IrSimpleFunction) (declaration.descriptor as? WrappedSimpleFunctionDescriptor)?.bind(declaration as IrSimpleFunction)
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
@@ -96,12 +96,12 @@ object WrappedDescriptorPatcher : IrElementVisitorVoid {
} }
override fun visitTypeParameter(declaration: IrTypeParameter) { override fun visitTypeParameter(declaration: IrTypeParameter) {
(declaration.descriptor as WrappedTypeParameterDescriptor).bind(declaration) (declaration.descriptor as? WrappedTypeParameterDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
override fun visitVariable(declaration: IrVariable) { override fun visitVariable(declaration: IrVariable) {
(declaration.descriptor as WrappedVariableDescriptor).bind(declaration) (declaration.descriptor as? WrappedVariableDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
} }