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.
|
// 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.irField: IrField get() = compilerContext.symbolTable.referenceField(this.descriptor).owner
|
||||||
|
|
||||||
val SerializableProperty.irProp: IrProperty
|
fun SerializableProperty.getIrPropertyFrom(thisClass: IrClass): IrProperty {
|
||||||
get() {
|
val desc = this.descriptor
|
||||||
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),
|
||||||
// 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.
|
||||||
// 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) {
|
||||||
return if (desc.module == compilerContext.moduleDescriptor) {
|
compilerContext.symbolTable.referenceProperty(desc).owner
|
||||||
compilerContext.symbolTable.referenceProperty(desc).owner
|
} else {
|
||||||
} else {
|
compilerContext.referenceProperties(desc.fqNameSafe).single().owner
|
||||||
compilerContext.referenceProperties(this.descriptor.fqNameSafe).single().owner
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.getProperty(receiver: IrExpression, property: IrProperty): IrExpression {
|
fun IrBuilderWithScope.getProperty(receiver: IrExpression, property: IrProperty): IrExpression {
|
||||||
return if (property.getter != null)
|
return if (property.getter != null)
|
||||||
|
|||||||
+5
-3
@@ -99,13 +99,15 @@ class SerializableIrGenerator(
|
|||||||
for (index in startPropOffset until serializableProperties.size) {
|
for (index in startPropOffset until serializableProperties.size) {
|
||||||
val prop = serializableProperties[index]
|
val prop = serializableProperties[index]
|
||||||
val paramRef = ctor.valueParameters[index + seenVarsOffset]
|
val paramRef = ctor.valueParameters[index + seenVarsOffset]
|
||||||
// assign this.a = a in else branch
|
// Assign this.a = a in else branch
|
||||||
val assignParamExpr = setProperty(irGet(thiz), prop.irProp, irGet(paramRef))
|
// 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 ifNotSeenExpr: IrExpression = if (prop.optional) {
|
||||||
val initializerBody =
|
val initializerBody =
|
||||||
requireNotNull(transformFieldInitializer(prop.irField)) { "Optional value without an initializer" } // todo: filter abstract here
|
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 {
|
} else {
|
||||||
// property required
|
// property required
|
||||||
if (useFieldMissingOptimization) {
|
if (useFieldMissingOptimization) {
|
||||||
|
|||||||
+2
-2
@@ -138,7 +138,7 @@ open class SerializerIrGenerator(
|
|||||||
if (classProp.transient) continue
|
if (classProp.transient) continue
|
||||||
+addFieldCall(classProp)
|
+addFieldCall(classProp)
|
||||||
// add property annotations
|
// add property annotations
|
||||||
val property = classProp.irProp
|
val property = classProp.getIrPropertyFrom(serializableIrClass)
|
||||||
copySerialInfoAnnotationsToDescriptor(
|
copySerialInfoAnnotationsToDescriptor(
|
||||||
property.annotations,
|
property.annotations,
|
||||||
localDescriptor,
|
localDescriptor,
|
||||||
@@ -268,7 +268,7 @@ open class SerializerIrGenerator(
|
|||||||
irGet(
|
irGet(
|
||||||
type = ownerType,
|
type = ownerType,
|
||||||
variable = objectToSerialize.symbol
|
variable = objectToSerialize.symbol
|
||||||
), irProp
|
), getIrPropertyFrom(serializableIrClass)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user