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.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
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.
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 {
@@ -108,6 +107,7 @@ fun IrDeclaration.toIrBasedDescriptor(): DeclarationDescriptor = when (this) {
is IrLocalDelegatedProperty -> toIrBasedDescriptor()
is IrFunction -> toIrBasedDescriptor()
is IrClass -> toIrBasedDescriptor()
is IrAnonymousInitializer -> parentAsClass.toIrBasedDescriptor()
is IrEnumEntry -> toIrBasedDescriptor()
is IrProperty -> toIrBasedDescriptor()
is IrField -> toIrBasedDescriptor()
@@ -1060,9 +1060,9 @@ private fun makeKotlinType(
hasQuestionMark: Boolean
): SimpleType =
when (classifier) {
is IrTypeParameterSymbol -> classifier.owner.toIrBasedDescriptor().defaultType
is IrTypeParameterSymbol -> classifier.toIrBasedDescriptorIfPossible().defaultType
is IrClassSymbol -> {
val classDescriptor = classifier.owner.toIrBasedDescriptor()
val classDescriptor = classifier.toIrBasedDescriptorIfPossible()
val kotlinTypeArguments = arguments.mapIndexed { index, it ->
when (it) {
is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toIrBasedKotlinType())
@@ -1094,3 +1094,20 @@ private fun makeKotlinType(
}
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.declarations.*
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.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature
@@ -27,9 +28,15 @@ import org.jetbrains.kotlin.ir.util.render
@OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class IrSymbolBase<out D : DeclarationDescriptor>(
private val _descriptor: D
) : IrSymbol {
@ObsoleteDescriptorBasedAPI
override val descriptor: D
) : IrSymbol {
get() = if (isBound && _descriptor is WrappedDeclarationDescriptor<*>)
(owner as IrDeclaration).toIrBasedDescriptor() as D
else
_descriptor
override fun toString(): String {
if (isBound) return owner.render()
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.declarations.*
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.util.IdSignature
import org.jetbrains.kotlin.ir.util.render
abstract class IrPublicSymbolBase<out D : DeclarationDescriptor> @OptIn(ObsoleteDescriptorBasedAPI::class) constructor(
@ObsoleteDescriptorBasedAPI
override val descriptor: D,
private val _descriptor: D,
override val signature: IdSignature
) : IrSymbol {
@ObsoleteDescriptorBasedAPI
override val descriptor: D
get() = if (isBound && _descriptor is WrappedDeclarationDescriptor<*>)
(owner as IrDeclaration).toIrBasedDescriptor() as D
else
_descriptor
override fun toString(): String {
if (isBound) return owner.render()
return "Unbound public symbol for $signature"
@@ -58,34 +58,34 @@ object WrappedDescriptorPatcher : IrElementVisitorVoid {
}
override fun visitClass(declaration: IrClass) {
(declaration.descriptor as WrappedClassDescriptor).bind(declaration)
(declaration.descriptor as? WrappedClassDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this)
}
override fun visitConstructor(declaration: IrConstructor) {
(declaration.descriptor as WrappedClassConstructorDescriptor).bind(declaration)
(declaration.descriptor as? WrappedClassConstructorDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this)
}
override fun visitEnumEntry(declaration: IrEnumEntry) {
(declaration.descriptor as WrappedClassDescriptor).bind(
(declaration.descriptor as? WrappedClassDescriptor)?.bind(
declaration.correspondingClass ?: declaration.parentAsClass
)
declaration.acceptChildrenVoid(this)
}
override fun visitField(declaration: IrField) {
(declaration.descriptor as WrappedFieldDescriptor).bind(declaration)
(declaration.descriptor as? WrappedFieldDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this)
}
override fun visitProperty(declaration: IrProperty) {
(declaration.descriptor as WrappedPropertyDescriptor).bind(declaration)
(declaration.descriptor as? WrappedPropertyDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this)
}
override fun visitFunction(declaration: IrFunction) {
(declaration.descriptor as WrappedSimpleFunctionDescriptor).bind(declaration as IrSimpleFunction)
(declaration.descriptor as? WrappedSimpleFunctionDescriptor)?.bind(declaration as IrSimpleFunction)
declaration.acceptChildrenVoid(this)
}
@@ -96,12 +96,12 @@ object WrappedDescriptorPatcher : IrElementVisitorVoid {
}
override fun visitTypeParameter(declaration: IrTypeParameter) {
(declaration.descriptor as WrappedTypeParameterDescriptor).bind(declaration)
(declaration.descriptor as? WrappedTypeParameterDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this)
}
override fun visitVariable(declaration: IrVariable) {
(declaration.descriptor as WrappedVariableDescriptor).bind(declaration)
(declaration.descriptor as? WrappedVariableDescriptor)?.bind(declaration)
declaration.acceptChildrenVoid(this)
}
}