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}>"),
propertyAccessor?.visibility ?: correspondingProperty.visibility,
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,
isOperator = false
).apply {
@@ -659,7 +661,8 @@ class Fir2IrDeclarationStorage(
IrFieldImpl(
startOffset, endOffset, origin, symbol,
name, inferredType,
visibility, isFinal = isFinal, isExternal = false,
visibility, isFinal = isFinal,
isExternal = property.isExternal,
isStatic = property.isStatic || parent !is IrClass,
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
).also {
@@ -712,8 +715,7 @@ class Fir2IrDeclarationStorage(
isConst = property.isConst,
isLateinit = property.isLateInit,
isDelegated = property.delegate != null,
// TODO
isExternal = false,
isExternal = property.isExternal,
isExpect = property.isExpect,
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
).apply {
@@ -940,16 +940,8 @@ class DeclarationsConverter(
}
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) }
val convertedAccessors = accessors.map { convertGetterOrSetter(it, returnType, propertyVisibility, modifiers) }
this.getter = convertedAccessors.find { it.isGetter }
?: FirDefaultPropertyGetter(null, session, FirDeclarationOrigin.Source, returnType, propertyVisibility)
this.setter =
@@ -958,6 +950,19 @@ class DeclarationsConverter(
?: FirDefaultPropertySetter(null, session, FirDeclarationOrigin.Source, returnType, propertyVisibility)
} 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 {
expressionConverter.getAsFirExpression<FirExpression>(it, "Should have delegate")
}
@@ -1031,7 +1036,8 @@ class DeclarationsConverter(
private fun convertGetterOrSetter(
getterOrSetter: LighterASTNode,
propertyTypeRef: FirTypeRef,
propertyVisibility: Visibility
propertyVisibility: Visibility,
propertyModifiers: Modifier
): FirPropertyAccessor {
var modifiers = Modifier()
var isGetter = true
@@ -1060,6 +1066,12 @@ class DeclarationsConverter(
if (accessorVisibility == Visibilities.UNKNOWN) {
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()
if (block == null && expression == null) {
return FirDefaultPropertyAccessor
@@ -1073,6 +1085,7 @@ class DeclarationsConverter(
)
.also {
it.annotations += modifiers.annotations
it.status = status
}
}
val target = FirFunctionTarget(labelName = null, isLambda = false)
@@ -1083,7 +1096,7 @@ class DeclarationsConverter(
returnTypeRef = returnType ?: if (isGetter) propertyTypeRef else implicitUnitType
symbol = FirPropertyAccessorSymbol()
this.isGetter = isGetter
status = FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL)
this.status = status
context.firFunctionTargets += target
annotations += modifiers.annotations
@@ -261,6 +261,14 @@ class RawFirBuilder(
): FirPropertyAccessor {
val accessorVisibility =
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()) {
val propertySource = property.toFirSourceElement()
return FirDefaultPropertyAccessor
@@ -276,6 +284,7 @@ class RawFirBuilder(
if (this != null) {
it.extractAnnotationsFrom(this)
}
it.status = status
}
}
val source = this.toFirSourceElement()
@@ -290,7 +299,7 @@ class RawFirBuilder(
returnTypeReference.toFirOrUnitType()
}
this.isGetter = isGetter
status = FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL)
this.status = status
extractAnnotationsTo(this)
this@RawFirBuilder.context.firFunctionTargets += accessorTarget
extractValueParametersTo(this, propertyTypeRef)
@@ -1078,19 +1087,25 @@ class RawFirBuilder(
expression = { delegateExpression }.toFirExpression("Should have delegate")
}
} 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 {
isExpect = hasExpectModifier()
isActual = hasActualModifier()
isOverride = hasModifier(OVERRIDE_KEYWORD)
isConst = hasModifier(CONST_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")
generateAccessorsByDelegate(
delegateBuilder,
@@ -1350,6 +1365,7 @@ class RawFirBuilder(
else -> null
}
val hasSubject = subjectExpression != null
@OptIn(FirContractViolation::class)
val ref = FirExpressionRef<FirWhenExpression>()
return buildWhenExpression {
@@ -63,6 +63,8 @@ inline val FirMemberDeclaration.isFromEnumClass: Boolean get() = status.isFromEn
inline val FirPropertyAccessor.modality get() = status.modality
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
get() = !Visibilities.isPrivate(visibility) && visibility != Visibilities.INVISIBLE_FAKE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: ANDROID
@@ -29,12 +29,12 @@ FILE fqName:<root> fileName:/implicitCastToTypeParameter.kt
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
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]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
$receiver: VALUE_PARAMETER name:<this> type:<root>.Foo<T of <root>.<get-asT>>
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
BRANCH
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> Any.classRefExtFun() = T::class