[FIR2IR] Move backing field creation in Fir2IrDeclarationStorage

This commit is contained in:
Mikhail Glukhikh
2020-04-06 11:23:08 +03:00
parent 882e6931d6
commit 4cb4aae7ee
2 changed files with 79 additions and 73 deletions
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.* import org.jetbrains.kotlin.builtins.KotlinBuiltIns.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
@@ -19,6 +16,7 @@ import org.jetbrains.kotlin.fir.descriptors.FirBuiltInsPackageFragment
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor
import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
@@ -36,10 +34,12 @@ import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.util.properties import org.jetbrains.kotlin.ir.util.properties
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -564,6 +564,39 @@ class Fir2IrDeclarationStorage(
} }
} }
private fun IrProperty.createBackingField(
property: FirProperty,
origin: IrDeclarationOrigin,
descriptor: PropertyDescriptor,
visibility: Visibility,
name: Name,
isFinal: Boolean,
firInitializerExpression: FirExpression?,
type: IrType? = null
): IrField {
val inferredType = type ?: firInitializerExpression!!.typeRef.toIrType()
return symbolTable.declareField(
startOffset, endOffset, origin, descriptor, inferredType
) { symbol ->
IrFieldImpl(
startOffset, endOffset, origin, symbol,
name, inferredType,
visibility, isFinal = isFinal, isExternal = false,
isStatic = property.isStatic || parent !is IrClass,
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
).also {
it.correspondingPropertySymbol = this@createBackingField.symbol
}
}
}
private val FirProperty.fieldVisibility: Visibility
get() = when {
isLateInit -> setter?.visibility ?: status.visibility
isConst -> status.visibility
else -> Visibilities.PRIVATE
}
fun createIrProperty( fun createIrProperty(
property: FirProperty, property: FirProperty,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
@@ -597,28 +630,51 @@ class Fir2IrDeclarationStorage(
} }
val type = property.returnTypeRef.toIrType() val type = property.returnTypeRef.toIrType()
val initializer = property.initializer val initializer = property.initializer
if (property.isConst && initializer is FirConstExpression<*>) { val delegate = property.delegate
backingField = IrFieldImpl(startOffset, endOffset, origin, descriptor, type).also { val getter = property.getter
it.initializer = IrExpressionBodyImpl(initializer.toIrConst(type)) val setter = property.setter
it.correspondingPropertySymbol = symbol // TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself
if (property.isConst || (property.modality != Modality.ABSTRACT && (irParent !is IrClass || !irParent.isInterface))) {
if (initializer != null || getter is FirDefaultPropertyGetter ||
property.isVar && setter is FirDefaultPropertySetter
) {
backingField = createBackingField(
property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, descriptor,
property.fieldVisibility, property.name, property.isVal, initializer, type
).also { field ->
if (initializer is FirConstExpression<*>) {
// TODO: Normally we shouldn't have error type here
val constType = initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type
field.initializer = IrExpressionBodyImpl(initializer.toIrConst(constType))
}
}
} else if (delegate != null) {
backingField = createBackingField(
property, IrDeclarationOrigin.PROPERTY_DELEGATE, descriptor,
property.fieldVisibility, Name.identifier("${property.name}\$delegate"), true, delegate
)
} }
if (irParent != null) {
backingField?.parent = irParent
}
} }
getter = createIrPropertyAccessor( this.getter = createIrPropertyAccessor(
property.getter, property, this, type, irParent, false, getter, property, this, type, irParent, false,
when { when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
property.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
property.getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin else -> origin
}, },
startOffset, endOffset startOffset, endOffset
) )
if (property.isVar) { if (property.isVar) {
setter = createIrPropertyAccessor( this.setter = createIrPropertyAccessor(
property.setter, property, this, type, irParent, true, setter, property, this, type, irParent, true,
when { when {
property.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
property.setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin else -> origin
}, },
startOffset, endOffset startOffset, endOffset
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.fir.backend.generators package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
@@ -20,10 +17,8 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
@@ -135,25 +130,8 @@ internal class ClassMemberGenerator(
val descriptor = irProperty.descriptor val descriptor = irProperty.descriptor
val initializer = property.initializer val initializer = property.initializer
val delegate = property.delegate val delegate = property.delegate
val irParent = irProperty.parent
val propertyType = property.returnTypeRef.toIrType() val propertyType = property.returnTypeRef.toIrType()
// TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself irProperty.initializeBackingField(descriptor, initializerExpression = initializer ?: delegate)
// TODO (2): backing field should be created inside declaration storage
if (property.modality != Modality.ABSTRACT && (irParent !is IrClass || !irParent.isInterface)) {
if (initializer != null || property.getter is FirDefaultPropertyGetter ||
property.isVar && property.setter is FirDefaultPropertySetter
) {
irProperty.backingField = irProperty.createBackingField(
property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, descriptor,
property.fieldVisibility, property.name, property.isVal, initializer, propertyType
)
} else if (delegate != null) {
irProperty.backingField = irProperty.createBackingField(
property, IrDeclarationOrigin.PROPERTY_DELEGATE, descriptor,
property.fieldVisibility, Name.identifier("${property.name}\$delegate"), true, delegate
)
}
}
irProperty.getter?.setPropertyAccessorContent( irProperty.getter?.setPropertyAccessorContent(
property.getter, irProperty, propertyType, property.getter is FirDefaultPropertyGetter property.getter, irProperty, propertyType, property.getter is FirDefaultPropertyGetter
) )
@@ -168,42 +146,14 @@ internal class ClassMemberGenerator(
return irProperty return irProperty
} }
private val FirProperty.fieldVisibility: Visibility private fun IrProperty.initializeBackingField(descriptor: PropertyDescriptor, initializerExpression: FirExpression?) {
get() = when { val irField = backingField ?: return
isLateInit -> setter?.visibility ?: status.visibility conversionScope.withParent(irField) {
isConst -> status.visibility
else -> Visibilities.PRIVATE
}
private fun IrProperty.createBackingField(
property: FirProperty,
origin: IrDeclarationOrigin,
descriptor: PropertyDescriptor,
visibility: Visibility,
name: Name,
isFinal: Boolean,
firInitializerExpression: FirExpression?,
type: IrType? = null
): IrField {
val inferredType = type ?: firInitializerExpression!!.typeRef.toIrType()
val irField = symbolTable.declareField(
startOffset, endOffset, origin, descriptor, inferredType
) { symbol ->
IrFieldImpl(
startOffset, endOffset, origin, symbol,
name, inferredType,
visibility, isFinal = isFinal, isExternal = false,
isStatic = property.isStatic || parent !is IrClass,
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
)
}
return conversionScope.withParent(applyParentFromStackTo(irField)) {
declarationStorage.enterScope(descriptor) declarationStorage.enterScope(descriptor)
if (firInitializerExpression != null) { // NB: initializer can be already converted
val initializerExpression = visitor.convertToIrExpression(firInitializerExpression) if (initializer == null && initializerExpression != null) {
initializer = IrExpressionBodyImpl(initializerExpression) initializer = IrExpressionBodyImpl(visitor.convertToIrExpression(initializerExpression))
} }
correspondingPropertySymbol = this@createBackingField.symbol
declarationStorage.leaveScope(descriptor) declarationStorage.leaveScope(descriptor)
} }
} }