Additional fix for Compose:
directly search for fields in IR class w/o using the symbol table. Because Compose copies whole IR, fields got referenced incorrectly. In the end, bytecode generator thinks that this is a field from other class and creates a synthetic setter, which is prohibited in Java 9+ (Update to non-static final field ... attempted from a different method than <init>)
This commit is contained in:
+9
-10
@@ -214,17 +214,16 @@ interface IrBuilderExtension {
|
||||
// note: this method should be used only for properties from current module. Fields from other modules are private and inaccessible.
|
||||
val SerializableProperty.irField: IrField get() = compilerContext.symbolTable.referenceField(this.descriptor).owner
|
||||
|
||||
val SerializableProperty.irProp: IrProperty
|
||||
get() {
|
||||
val desc = this.descriptor
|
||||
// this API is used to reference both current module descriptors and external ones (because serializable class can be in any of them),
|
||||
// so we use descriptor api for current module because it is not possible to obtain FQname for e.g. local classes.
|
||||
return if (desc.module == compilerContext.moduleDescriptor) {
|
||||
compilerContext.symbolTable.referenceProperty(desc).owner
|
||||
} else {
|
||||
compilerContext.referenceProperties(this.descriptor.fqNameSafe).single().owner
|
||||
}
|
||||
fun SerializableProperty.getIrPropertyFrom(thisClass: IrClass): IrProperty {
|
||||
val desc = this.descriptor
|
||||
// this API is used to reference both current module descriptors and external ones (because serializable class can be in any of them),
|
||||
// so we use descriptor api for current module because it is not possible to obtain FQname for e.g. local classes.
|
||||
return thisClass.searchForDeclaration(desc) ?: if (desc.module == compilerContext.moduleDescriptor) {
|
||||
compilerContext.symbolTable.referenceProperty(desc).owner
|
||||
} else {
|
||||
compilerContext.referenceProperties(desc.fqNameSafe).single().owner
|
||||
}
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.getProperty(receiver: IrExpression, property: IrProperty): IrExpression {
|
||||
return if (property.getter != null)
|
||||
|
||||
+5
-3
@@ -99,13 +99,15 @@ class SerializableIrGenerator(
|
||||
for (index in startPropOffset until serializableProperties.size) {
|
||||
val prop = serializableProperties[index]
|
||||
val paramRef = ctor.valueParameters[index + seenVarsOffset]
|
||||
// assign this.a = a in else branch
|
||||
val assignParamExpr = setProperty(irGet(thiz), prop.irProp, irGet(paramRef))
|
||||
// Assign this.a = a in else branch
|
||||
// Set field directly w/o setter to match behavior of old backend plugin
|
||||
val backingFieldToAssign = prop.getIrPropertyFrom(irClass).backingField!!
|
||||
val assignParamExpr = irSetField(irGet(thiz), backingFieldToAssign, irGet(paramRef))
|
||||
|
||||
val ifNotSeenExpr: IrExpression = if (prop.optional) {
|
||||
val initializerBody =
|
||||
requireNotNull(transformFieldInitializer(prop.irField)) { "Optional value without an initializer" } // todo: filter abstract here
|
||||
setProperty(irGet(thiz), prop.irProp, initializerBody)
|
||||
irSetField(irGet(thiz), backingFieldToAssign, initializerBody)
|
||||
} else {
|
||||
// property required
|
||||
if (useFieldMissingOptimization) {
|
||||
|
||||
+2
-2
@@ -138,7 +138,7 @@ open class SerializerIrGenerator(
|
||||
if (classProp.transient) continue
|
||||
+addFieldCall(classProp)
|
||||
// add property annotations
|
||||
val property = classProp.irProp
|
||||
val property = classProp.getIrPropertyFrom(serializableIrClass)
|
||||
copySerialInfoAnnotationsToDescriptor(
|
||||
property.annotations,
|
||||
localDescriptor,
|
||||
@@ -268,7 +268,7 @@ open class SerializerIrGenerator(
|
||||
irGet(
|
||||
type = ownerType,
|
||||
variable = objectToSerialize.symbol
|
||||
), irProp
|
||||
), getIrPropertyFrom(serializableIrClass)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user