From 4cb4aae7eeff98ce22ed0ec5e003039e4bf8ff97 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 6 Apr 2020 11:23:08 +0300 Subject: [PATCH] [FIR2IR] Move backing field creation in Fir2IrDeclarationStorage --- .../fir/backend/Fir2IrDeclarationStorage.kt | 88 +++++++++++++++---- .../generators/ClassMemberGenerator.kt | 64 ++------------ 2 files changed, 79 insertions(+), 73 deletions(-) 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 aef3b333da3..6733d83f379 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 @@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.builtins.KotlinBuiltIns.* -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.fir.declarations.* 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.FirPackageFragmentDescriptor 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.psi 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.IrExpressionBodyImpl 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.IrType import org.jetbrains.kotlin.ir.util.constructors 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.name.ClassId 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( property: FirProperty, irParent: IrDeclarationParent?, @@ -597,28 +630,51 @@ class Fir2IrDeclarationStorage( } val type = property.returnTypeRef.toIrType() val initializer = property.initializer - if (property.isConst && initializer is FirConstExpression<*>) { - backingField = IrFieldImpl(startOffset, endOffset, origin, descriptor, type).also { - it.initializer = IrExpressionBodyImpl(initializer.toIrConst(type)) - it.correspondingPropertySymbol = symbol + val delegate = property.delegate + val getter = property.getter + val setter = property.setter + // 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( - property.getter, property, this, type, irParent, false, + this.getter = createIrPropertyAccessor( + getter, property, this, type, irParent, false, when { origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin - property.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR - property.getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR + delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR + getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR else -> origin }, startOffset, endOffset ) if (property.isVar) { - setter = createIrPropertyAccessor( - property.setter, property, this, type, irParent, true, + this.setter = createIrPropertyAccessor( + setter, property, this, type, irParent, true, when { - property.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR - property.setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR + delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR + setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR else -> origin }, startOffset, endOffset diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index c14561a8f05..b648186252c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.fir.backend.generators -import org.jetbrains.kotlin.descriptors.Modality 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.declarations.* 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.types.* 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.IrFieldAccessExpression -import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.types.IrType @@ -135,25 +130,8 @@ internal class ClassMemberGenerator( val descriptor = irProperty.descriptor val initializer = property.initializer val delegate = property.delegate - val irParent = irProperty.parent val propertyType = property.returnTypeRef.toIrType() - // TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself - // 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.initializeBackingField(descriptor, initializerExpression = initializer ?: delegate) irProperty.getter?.setPropertyAccessorContent( property.getter, irProperty, propertyType, property.getter is FirDefaultPropertyGetter ) @@ -168,42 +146,14 @@ internal class ClassMemberGenerator( return irProperty } - private val FirProperty.fieldVisibility: Visibility - get() = when { - isLateInit -> setter?.visibility ?: status.visibility - 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)) { + private fun IrProperty.initializeBackingField(descriptor: PropertyDescriptor, initializerExpression: FirExpression?) { + val irField = backingField ?: return + conversionScope.withParent(irField) { declarationStorage.enterScope(descriptor) - if (firInitializerExpression != null) { - val initializerExpression = visitor.convertToIrExpression(firInitializerExpression) - initializer = IrExpressionBodyImpl(initializerExpression) + // NB: initializer can be already converted + if (initializer == null && initializerExpression != null) { + initializer = IrExpressionBodyImpl(visitor.convertToIrExpression(initializerExpression)) } - correspondingPropertySymbol = this@createBackingField.symbol declarationStorage.leaveScope(descriptor) } }