FIR: inherit property accessor modifiers from property and vice versa

This commit is contained in:
Jinseong Jeon
2020-06-10 15:08:12 -07:00
committed by Mikhail Glukhikh
parent 6f957c7b31
commit f64f9c2144
8 changed files with 57 additions and 85 deletions
@@ -602,7 +602,9 @@ class Fir2IrDeclarationStorage(
Name.special("<$prefix-${correspondingProperty.name}>"), Name.special("<$prefix-${correspondingProperty.name}>"),
propertyAccessor?.visibility ?: correspondingProperty.visibility, propertyAccessor?.visibility ?: correspondingProperty.visibility,
correspondingProperty.modality, accessorReturnType, correspondingProperty.modality, accessorReturnType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isExpect = false, isInline = propertyAccessor?.isInline == true,
isExternal = propertyAccessor?.isExternal == true,
isTailrec = false, isSuspend = false, isExpect = false,
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE, isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE,
isOperator = false isOperator = false
).apply { ).apply {
@@ -659,7 +661,8 @@ class Fir2IrDeclarationStorage(
IrFieldImpl( IrFieldImpl(
startOffset, endOffset, origin, symbol, startOffset, endOffset, origin, symbol,
name, inferredType, name, inferredType,
visibility, isFinal = isFinal, isExternal = false, visibility, isFinal = isFinal,
isExternal = property.isExternal,
isStatic = property.isStatic || parent !is IrClass, isStatic = property.isStatic || parent !is IrClass,
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
).also { ).also {
@@ -712,8 +715,7 @@ class Fir2IrDeclarationStorage(
isConst = property.isConst, isConst = property.isConst,
isLateinit = property.isLateInit, isLateinit = property.isLateInit,
isDelegated = property.delegate != null, isDelegated = property.delegate != null,
// TODO isExternal = property.isExternal,
isExternal = false,
isExpect = property.isExpect, isExpect = property.isExpect,
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
).apply { ).apply {
@@ -940,16 +940,8 @@ class DeclarationsConverter(
} }
val propertyVisibility = modifiers.getVisibility() val propertyVisibility = modifiers.getVisibility()
status = FirDeclarationStatusImpl(propertyVisibility, modifiers.getModality()).apply {
isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride()
isConst = modifiers.isConst()
isLateInit = modifiers.hasLateinit()
}
val convertedAccessors = accessors.map { convertGetterOrSetter(it, returnType, propertyVisibility, modifiers) }
val convertedAccessors = accessors.map { convertGetterOrSetter(it, returnType, propertyVisibility) }
this.getter = convertedAccessors.find { it.isGetter } this.getter = convertedAccessors.find { it.isGetter }
?: FirDefaultPropertyGetter(null, session, FirDeclarationOrigin.Source, returnType, propertyVisibility) ?: FirDefaultPropertyGetter(null, session, FirDeclarationOrigin.Source, returnType, propertyVisibility)
this.setter = this.setter =
@@ -958,6 +950,19 @@ class DeclarationsConverter(
?: FirDefaultPropertySetter(null, session, FirDeclarationOrigin.Source, returnType, propertyVisibility) ?: FirDefaultPropertySetter(null, session, FirDeclarationOrigin.Source, returnType, propertyVisibility)
} else null } else null
// Upward propagation of `inline` and `external` modifiers (from accessors to property)
// Note that, depending on `var` or `val`, checking setter's modifiers should be careful: for `val`, setter doesn't
// exist (null); for `var`, the retrieval of the specific modifier is supposed to be `true`
status = FirDeclarationStatusImpl(propertyVisibility, modifiers.getModality()).apply {
isExpect = modifiers.hasExpect()
isActual = modifiers.hasActual()
isOverride = modifiers.hasOverride()
isConst = modifiers.isConst()
isLateInit = modifiers.hasLateinit()
isInline = modifiers.hasInline() || (getter!!.isInline && setter?.isInline != false)
isExternal = modifiers.hasExternal() || (getter!!.isExternal && setter?.isExternal != false)
}
val receiver = delegateExpression?.let { val receiver = delegateExpression?.let {
expressionConverter.getAsFirExpression<FirExpression>(it, "Should have delegate") expressionConverter.getAsFirExpression<FirExpression>(it, "Should have delegate")
} }
@@ -1031,7 +1036,8 @@ class DeclarationsConverter(
private fun convertGetterOrSetter( private fun convertGetterOrSetter(
getterOrSetter: LighterASTNode, getterOrSetter: LighterASTNode,
propertyTypeRef: FirTypeRef, propertyTypeRef: FirTypeRef,
propertyVisibility: Visibility propertyVisibility: Visibility,
propertyModifiers: Modifier
): FirPropertyAccessor { ): FirPropertyAccessor {
var modifiers = Modifier() var modifiers = Modifier()
var isGetter = true var isGetter = true
@@ -1060,6 +1066,12 @@ class DeclarationsConverter(
if (accessorVisibility == Visibilities.UNKNOWN) { if (accessorVisibility == Visibilities.UNKNOWN) {
accessorVisibility = propertyVisibility accessorVisibility = propertyVisibility
} }
val status =
// Downward propagation of `inline` and `external` modifiers (from property to its accessors)
FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL).apply {
isInline = propertyModifiers.hasInline() || modifiers.hasInline()
isExternal = propertyModifiers.hasExternal() || modifiers.hasExternal()
}
val sourceElement = getterOrSetter.toFirSourceElement() val sourceElement = getterOrSetter.toFirSourceElement()
if (block == null && expression == null) { if (block == null && expression == null) {
return FirDefaultPropertyAccessor return FirDefaultPropertyAccessor
@@ -1073,6 +1085,7 @@ class DeclarationsConverter(
) )
.also { .also {
it.annotations += modifiers.annotations it.annotations += modifiers.annotations
it.status = status
} }
} }
val target = FirFunctionTarget(labelName = null, isLambda = false) val target = FirFunctionTarget(labelName = null, isLambda = false)
@@ -1083,7 +1096,7 @@ class DeclarationsConverter(
returnTypeRef = returnType ?: if (isGetter) propertyTypeRef else implicitUnitType returnTypeRef = returnType ?: if (isGetter) propertyTypeRef else implicitUnitType
symbol = FirPropertyAccessorSymbol() symbol = FirPropertyAccessorSymbol()
this.isGetter = isGetter this.isGetter = isGetter
status = FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL) this.status = status
context.firFunctionTargets += target context.firFunctionTargets += target
annotations += modifiers.annotations annotations += modifiers.annotations
@@ -261,6 +261,14 @@ class RawFirBuilder(
): FirPropertyAccessor { ): FirPropertyAccessor {
val accessorVisibility = val accessorVisibility =
if (this?.visibility != null && this.visibility != Visibilities.UNKNOWN) this.visibility else property.visibility if (this?.visibility != null && this.visibility != Visibilities.UNKNOWN) this.visibility else property.visibility
// Downward propagation of `inline` and `external` modifiers (from property to its accessors)
val status =
FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL).apply {
isInline = property.hasModifier(INLINE_KEYWORD) ||
this@toFirPropertyAccessor?.hasModifier(INLINE_KEYWORD) == true
isExternal = property.hasModifier(EXTERNAL_KEYWORD) ||
this@toFirPropertyAccessor?.hasModifier(EXTERNAL_KEYWORD) == true
}
if (this == null || !hasBody()) { if (this == null || !hasBody()) {
val propertySource = property.toFirSourceElement() val propertySource = property.toFirSourceElement()
return FirDefaultPropertyAccessor return FirDefaultPropertyAccessor
@@ -276,6 +284,7 @@ class RawFirBuilder(
if (this != null) { if (this != null) {
it.extractAnnotationsFrom(this) it.extractAnnotationsFrom(this)
} }
it.status = status
} }
} }
val source = this.toFirSourceElement() val source = this.toFirSourceElement()
@@ -290,7 +299,7 @@ class RawFirBuilder(
returnTypeReference.toFirOrUnitType() returnTypeReference.toFirOrUnitType()
} }
this.isGetter = isGetter this.isGetter = isGetter
status = FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL) this.status = status
extractAnnotationsTo(this) extractAnnotationsTo(this)
this@RawFirBuilder.context.firFunctionTargets += accessorTarget this@RawFirBuilder.context.firFunctionTargets += accessorTarget
extractValueParametersTo(this, propertyTypeRef) extractValueParametersTo(this, propertyTypeRef)
@@ -1078,19 +1087,25 @@ class RawFirBuilder(
expression = { delegateExpression }.toFirExpression("Should have delegate") expression = { delegateExpression }.toFirExpression("Should have delegate")
} }
} else null } else null
getter = this@toFirProperty.getter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = true)
setter = if (isVar) {
this@toFirProperty.setter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = false)
} else null
// Upward propagation of `inline` and `external` modifiers (from accessors to property)
// Note that, depending on `var` or `val`, checking setter's modifiers should be careful: for `val`, setter doesn't
// exist (null); for `var`, the retrieval of the specific modifier is supposed to be `true`
status = FirDeclarationStatusImpl(visibility, modality).apply { status = FirDeclarationStatusImpl(visibility, modality).apply {
isExpect = hasExpectModifier() isExpect = hasExpectModifier()
isActual = hasActualModifier() isActual = hasActualModifier()
isOverride = hasModifier(OVERRIDE_KEYWORD) isOverride = hasModifier(OVERRIDE_KEYWORD)
isConst = hasModifier(CONST_KEYWORD) isConst = hasModifier(CONST_KEYWORD)
isLateInit = hasModifier(LATEINIT_KEYWORD) isLateInit = hasModifier(LATEINIT_KEYWORD)
isInline = hasModifier(INLINE_KEYWORD) || (getter!!.isInline && setter?.isInline != false)
isExternal = hasModifier(EXTERNAL_KEYWORD) || (getter!!.isExternal && setter?.isExternal != false)
} }
getter = this@toFirProperty.getter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = true)
setter = if (isVar) {
this@toFirProperty.setter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = false)
} else null
val receiver = delegateExpression?.toFirExpression("Should have delegate") val receiver = delegateExpression?.toFirExpression("Should have delegate")
generateAccessorsByDelegate( generateAccessorsByDelegate(
delegateBuilder, delegateBuilder,
@@ -1350,6 +1365,7 @@ class RawFirBuilder(
else -> null else -> null
} }
val hasSubject = subjectExpression != null val hasSubject = subjectExpression != null
@OptIn(FirContractViolation::class) @OptIn(FirContractViolation::class)
val ref = FirExpressionRef<FirWhenExpression>() val ref = FirExpressionRef<FirWhenExpression>()
return buildWhenExpression { return buildWhenExpression {
@@ -63,6 +63,8 @@ inline val FirMemberDeclaration.isFromEnumClass: Boolean get() = status.isFromEn
inline val FirPropertyAccessor.modality get() = status.modality inline val FirPropertyAccessor.modality get() = status.modality
inline val FirPropertyAccessor.visibility get() = status.visibility inline val FirPropertyAccessor.visibility get() = status.visibility
inline val FirPropertyAccessor.isInline get() = status.isInline
inline val FirPropertyAccessor.isExternal get() = status.isExternal
inline val FirPropertyAccessor.allowsToHaveFakeOverride: Boolean inline val FirPropertyAccessor.allowsToHaveFakeOverride: Boolean
get() = !Visibilities.isPrivate(visibility) && visibility != Visibilities.INVISIBLE_FAKE get() = !Visibilities.isPrivate(visibility) && visibility != Visibilities.INVISIBLE_FAKE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// IGNORE_BACKEND: ANDROID // IGNORE_BACKEND: ANDROID
@@ -29,12 +29,12 @@ FILE fqName:<root> fileName:/implicitCastToTypeParameter.kt
public open fun toString (): kotlin.String declared in kotlin.Any public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
PROPERTY name:asT visibility:public modality:FINAL [val] PROPERTY name:asT visibility:public modality:FINAL [val]
FUN name:<get-asT> visibility:public modality:FINAL <T> ($receiver:<root>.Foo<T of <root>.<get-asT>>) returnType:T of <root>.<get-asT>? FUN name:<get-asT> visibility:public modality:FINAL <T> ($receiver:<root>.Foo<T of <root>.<get-asT>>) returnType:T of <root>.<get-asT>? [inline]
correspondingProperty: PROPERTY name:asT visibility:public modality:FINAL [val] correspondingProperty: PROPERTY name:asT visibility:public modality:FINAL [val]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any] TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
$receiver: VALUE_PARAMETER name:<this> type:<root>.Foo<T of <root>.<get-asT>> $receiver: VALUE_PARAMETER name:<this> type:<root>.Foo<T of <root>.<get-asT>>
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-asT> <T> (): T of <root>.<get-asT>? declared in <root>' RETURN type=kotlin.Nothing from='public final fun <get-asT> <T> (): T of <root>.<get-asT>? [inline] declared in <root>'
WHEN type=T of <root>.<get-asT>? origin=IF WHEN type=T of <root>.<get-asT>? origin=IF
BRANCH BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=T of <root>.<get-asT> if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=T of <root>.<get-asT>
@@ -1,61 +0,0 @@
FILE fqName:<root> fileName:/typeParameterClassLiteral.kt
FUN name:classRefFun visibility:public modality:FINAL <T> () returnType:kotlin.reflect.KClass<T of <root>.classRefFun> [inline]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun classRefFun <T> (): kotlin.reflect.KClass<T of <root>.classRefFun> [inline] declared in <root>'
CLASS_REFERENCE 'TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<T of <root>.classRefFun>
FUN name:classRefExtFun visibility:public modality:FINAL <T> ($receiver:kotlin.Any) returnType:kotlin.reflect.KClass<T of <root>.classRefExtFun> [inline]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
$receiver: VALUE_PARAMETER name:<this> type:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun classRefExtFun <T> (): kotlin.reflect.KClass<T of <root>.classRefExtFun> [inline] declared in <root>'
CLASS_REFERENCE 'TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<T of <root>.classRefExtFun>
PROPERTY name:classRefExtVal visibility:public modality:FINAL [val]
FUN name:<get-classRefExtVal> visibility:public modality:FINAL <T> ($receiver:T of <root>.<get-classRefExtVal>) returnType:kotlin.reflect.KClass<T of <root>.<get-classRefExtVal>>
correspondingProperty: PROPERTY name:classRefExtVal visibility:public modality:FINAL [val]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
$receiver: VALUE_PARAMETER name:<this> type:T of <root>.<get-classRefExtVal>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-classRefExtVal> <T> (): kotlin.reflect.KClass<T of <root>.<get-classRefExtVal>> declared in <root>'
CLASS_REFERENCE 'TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<T of <root>.<get-classRefExtVal>>
CLASS CLASS name:Host modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Host
CONSTRUCTOR visibility:public <> () returnType:<root>.Host [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Host modality:FINAL visibility:public superTypes:[kotlin.Any]'
FUN name:classRefGenericMemberFun visibility:public modality:FINAL <TF> ($this:<root>.Host) returnType:kotlin.reflect.KClass<TF of <root>.Host.classRefGenericMemberFun> [inline]
TYPE_PARAMETER name:TF index:0 variance: superTypes:[kotlin.Any]
$this: VALUE_PARAMETER name:<this> type:<root>.Host
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun classRefGenericMemberFun <TF> (): kotlin.reflect.KClass<TF of <root>.Host.classRefGenericMemberFun> [inline] declared in <root>.Host'
CLASS_REFERENCE 'TYPE_PARAMETER name:TF index:0 variance: superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<TF of <root>.Host.classRefGenericMemberFun>
FUN name:classRefGenericMemberExtFun visibility:public modality:FINAL <TF> ($this:<root>.Host, $receiver:kotlin.Any) returnType:kotlin.reflect.KClass<TF of <root>.Host.classRefGenericMemberExtFun> [inline]
TYPE_PARAMETER name:TF index:0 variance: superTypes:[kotlin.Any]
$this: VALUE_PARAMETER name:<this> type:<root>.Host
$receiver: VALUE_PARAMETER name:<this> type:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun classRefGenericMemberExtFun <TF> (): kotlin.reflect.KClass<TF of <root>.Host.classRefGenericMemberExtFun> [inline] declared in <root>.Host'
CLASS_REFERENCE 'TYPE_PARAMETER name:TF index:0 variance: superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<TF of <root>.Host.classRefGenericMemberExtFun>
PROPERTY name:classRefGenericMemberExtVal visibility:public modality:FINAL [val]
FUN name:<get-classRefGenericMemberExtVal> visibility:public modality:FINAL <TV> ($this:<root>.Host, $receiver:TV of <root>.Host.<get-classRefGenericMemberExtVal>) returnType:kotlin.reflect.KClass<TV of <root>.Host.<get-classRefGenericMemberExtVal>>
correspondingProperty: PROPERTY name:classRefGenericMemberExtVal visibility:public modality:FINAL [val]
TYPE_PARAMETER name:TV index:0 variance: superTypes:[kotlin.Any]
$this: VALUE_PARAMETER name:<this> type:<root>.Host
$receiver: VALUE_PARAMETER name:<this> type:TV of <root>.Host.<get-classRefGenericMemberExtVal>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-classRefGenericMemberExtVal> <TV> (): kotlin.reflect.KClass<TV of <root>.Host.<get-classRefGenericMemberExtVal>> declared in <root>.Host'
CLASS_REFERENCE 'TYPE_PARAMETER name:TV index:0 variance: superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<TV of <root>.Host.<get-classRefGenericMemberExtVal>>
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
inline fun <reified T : Any> classRefFun() = T::class inline fun <reified T : Any> classRefFun() = T::class
inline fun <reified T : Any> Any.classRefExtFun() = T::class inline fun <reified T : Any> Any.classRefExtFun() = T::class