FIR: Do not load inline flag when deserializing properties; there is

no `inline` flag for serialized properties.

In order to test this, I added the changes to FirRenderer to make sure
the flag is not loaded. However, this revealed that the `inline` status
was propagated upward to the `FirProperty` during raw FIR building,
causing test failures.

I removed the upward propagation for `inline`. I also removed it for
`external` because it is incorrect: `external` on properties (used in
JS) should be separate from `external` on accessors (used in JNI
interop for JVM). The `external` flags are also serialized separately
for properties and accessors.
This commit is contained in:
Mark Punzalan
2021-03-16 18:25:15 +00:00
committed by teamcityserver
parent 030697d430
commit efe3f7b87e
8 changed files with 57 additions and 65 deletions
@@ -57,8 +57,18 @@ internal fun FirMemberDeclaration.isEffectivelyExternal(
): Boolean {
if (this.isExternal) return true
// NB: [MemberDescriptor.isEffectivelyExternal] checks property accessors for property and vice versa.
// But, raw FIR creation already did such upward/downward propagation of modifiers.
if (this is FirPropertyAccessor) {
// Check containing property
val property = context.containingDeclarations.last() as FirProperty
return property.isEffectivelyExternal(containingClass, context)
}
if (this is FirProperty) {
// Property is effectively external if all accessors are external
if (getter?.isExternal == true && (!isVar || setter?.isExternal == true)) {
return true
}
}
return containingClass != null && isInsideExternalClass(containingClass, context)
}
@@ -337,7 +337,6 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
isOverride = false
isConst = Flags.IS_CONST.get(flags)
isLateInit = Flags.IS_LATEINIT.get(flags)
isInline = Flags.IS_INLINE.get(flags)
isExternal = Flags.IS_EXTERNAL_PROPERTY.get(flags)
}
@@ -1099,17 +1099,13 @@ class DeclarationsConverter(
}
} 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(isClassOrObject = false)).apply {
isExpect = modifiers.hasExpect() || classWrapper?.hasExpect() == true
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)
isExternal = modifiers.hasExternal()
}
val receiver = delegateExpression?.let {
@@ -1341,17 +1341,13 @@ open class RawFirBuilder(
getter = this@toFirProperty.getter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = true)
setter = this@toFirProperty.setter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = false)
// 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() || containingClassOrObject?.hasExpectModifier() == true
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)
isExternal = hasModifier(EXTERNAL_KEYWORD)
}
val receiver = delegateExpression?.toFirExpression("Should have delegate")
@@ -20,6 +20,6 @@ FILE: external.kt
public? set(value: Int): R|kotlin/Unit| { LAZY_BLOCK }
}
public? final? external var z: Int
public? final? var z: Int
public? external get(): Int
public? external set(value: Int): R|kotlin/Unit|
@@ -21,6 +21,6 @@ FILE: external.kt
}
}
public? final? external var z: Int
public? final? var z: Int
public? external get(): Int
public? external set(value: Int): R|kotlin/Unit|
@@ -314,50 +314,45 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
if (memberDeclaration.isExternal) {
print("external ")
}
if (memberDeclaration is FirCallableMemberDeclaration<*>) {
if (memberDeclaration.isOverride) {
print("override ")
}
if (memberDeclaration.isStatic) {
print("static ")
}
if (memberDeclaration.isOverride) {
print("override ")
}
if (memberDeclaration is FirRegularClass) {
if (memberDeclaration.isInner) {
print("inner ")
}
if (memberDeclaration.isCompanion) {
print("companion ")
}
if (memberDeclaration.isData) {
print("data ")
}
if (memberDeclaration.isInline) {
print("inline ")
}
} else if (memberDeclaration is FirSimpleFunction) {
if (memberDeclaration.isOperator) {
print("operator ")
}
if (memberDeclaration.isInfix) {
print("infix ")
}
if (memberDeclaration.isInline) {
print("inline ")
}
if (memberDeclaration.isTailRec) {
print("tailrec ")
}
if (memberDeclaration.isSuspend) {
print("suspend ")
}
} else if (memberDeclaration is FirProperty) {
if (memberDeclaration.isConst) {
print("const ")
}
if (memberDeclaration.isLateInit) {
print("lateinit ")
}
if (memberDeclaration.isStatic) {
print("static ")
}
if (memberDeclaration.isInner) {
print("inner ")
}
// `companion/data` modifiers are only valid for FirRegularClass, but we render them to make sure they are not
// incorrectly loaded for other declarations during deserialization.
if (memberDeclaration.status.isCompanion) {
print("companion ")
}
if (memberDeclaration.status.isData) {
print("data ")
}
if (memberDeclaration.isInline) {
print("inline ")
}
if (memberDeclaration.isOperator) {
print("operator ")
}
if (memberDeclaration.isInfix) {
print("infix ")
}
if (memberDeclaration.isTailRec) {
print("tailrec ")
}
if (memberDeclaration.isSuspend) {
print("suspend ")
}
if (memberDeclaration.isConst) {
print("const ")
}
if (memberDeclaration.isLateInit) {
print("lateinit ")
}
visitDeclaration(memberDeclaration)
@@ -49,16 +49,13 @@ inline val FirClass<*>.isEnumClass: Boolean
inline val FirRegularClass.modality get() = status.modality
inline val FirRegularClass.isSealed get() = status.modality == Modality.SEALED
inline val FirRegularClass.isAbstract get() = status.modality == Modality.ABSTRACT
inline val FirRegularClass.isFun get() = status.isFun
inline val FirRegularClass.isCompanion get() = status.isCompanion
inline val FirRegularClass.isData get() = status.isData
inline val FirRegularClass.canHaveAbstractDeclaration: Boolean
get() = isAbstract || isSealed || isEnumClass
inline val FirRegularClass.isInner get() = status.isInner
inline val FirRegularClass.isCompanion get() = status.isCompanion
inline val FirRegularClass.isData get() = status.isData
inline val FirRegularClass.isInline get() = status.isInline
inline val FirRegularClass.isFun get() = status.isFun
inline val FirMemberDeclaration.modality get() = status.modality
inline val FirMemberDeclaration.isAbstract get() = status.modality == Modality.ABSTRACT
inline val FirMemberDeclaration.isOpen get() = status.modality == Modality.OPEN
@@ -92,7 +89,6 @@ inline val FirMemberDeclaration.isConst: Boolean get() = status.isConst
inline val FirMemberDeclaration.isLateInit: Boolean get() = status.isLateInit
inline val FirMemberDeclaration.isFromSealedClass: Boolean get() = status.isFromSealedClass
inline val FirMemberDeclaration.isFromEnumClass: Boolean get() = status.isFromEnumClass
inline val FirMemberDeclaration.isFun: Boolean get() = status.isFun
inline val FirFunction<*>.hasBody get() = body != null