Fix compilation error when @Serializable expect class has explicit companion
as it may have no primary constructor (only actual class has it). Refactor & rename Fir2IrGeneratorUtils.kt as having 'Fir' in stacktrace when actual K2 compiler is not used is very confusing. Fixes https://github.com/Kotlin/kotlinx.serialization/issues/2134 #KT-55683 Fixed
This commit is contained in:
committed by
Space Team
parent
6d3812c259
commit
2634303055
+2
-5
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.primaryConstructor
|
||||
|
||||
// TODO KT-53096
|
||||
@@ -38,9 +37,7 @@ fun IrPluginContext.generateBodyForDefaultConstructor(declaration: IrConstructor
|
||||
return irFactory.createBlockBody(-1, -1, listOf(delegatingAnyCall, initializerCall))
|
||||
}
|
||||
|
||||
val Sequence<IrConstructor>.primary get() = find { it.isPrimary } ?: error("Expected to have a primary constructor")
|
||||
|
||||
fun IrClass.addDefaultConstructorIfAbsent(ctx: IrPluginContext) {
|
||||
val declaration = constructors.primary
|
||||
fun IrClass.addDefaultConstructorBodyIfAbsent(ctx: IrPluginContext) {
|
||||
val declaration = primaryConstructor ?: return
|
||||
if (declaration.body == null) declaration.body = ctx.generateBodyForDefaultConstructor(declaration)
|
||||
}
|
||||
+3
@@ -208,6 +208,9 @@ internal val List<IrConstructorCall>.hasAnySerialAnnotation: Boolean
|
||||
internal val List<IrConstructorCall>.serialNameValue: String?
|
||||
get() = findAnnotation(SerializationAnnotations.serialNameAnnotationFqName)?.getStringConstArgument(0) // @SerialName("foo")
|
||||
|
||||
|
||||
val IrClass.primaryConstructorOrFail get() = primaryConstructor ?: error("$this is expected to have a primary constructor")
|
||||
|
||||
/**
|
||||
* True — ALWAYS
|
||||
* False — NEVER
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ class SerializableCompanionIrGenerator(
|
||||
val serializableClass = getSerializableClassByCompanion(companionDescriptor) ?: return
|
||||
if (serializableClass.shouldHaveGeneratedMethodsInCompanion) {
|
||||
SerializableCompanionIrGenerator(irClass, getSerializableClassByCompanion(irClass)!!, context).generate()
|
||||
irClass.addDefaultConstructorIfAbsent(context)
|
||||
irClass.addDefaultConstructorBodyIfAbsent(context)
|
||||
irClass.patchDeclarationParents(irClass.parent)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -199,7 +199,7 @@ open class SerializerIrGenerator(
|
||||
fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: IrConstructor) =
|
||||
addFunctionBody(typedConstructorDescriptor) { ctor ->
|
||||
// generate call to primary ctor to init serialClassDesc and super()
|
||||
val primaryCtor = irClass.constructors.primary
|
||||
val primaryCtor = irClass.primaryConstructorOrFail
|
||||
+IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||
startOffset,
|
||||
endOffset,
|
||||
@@ -518,7 +518,7 @@ open class SerializerIrGenerator(
|
||||
|
||||
generateGoldenMaskCheck(bitMasks, properties, localSerialDesc.get())
|
||||
|
||||
val ctor: IrConstructorSymbol = serializableIrClass.constructors.primary.symbol
|
||||
val ctor: IrConstructorSymbol = serializableIrClass.primaryConstructorOrFail.symbol
|
||||
val params = ctor.owner.valueParameters
|
||||
|
||||
val variableByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = { vpd ->
|
||||
@@ -642,7 +642,7 @@ open class SerializerIrGenerator(
|
||||
// replace origin only for plugin generated serializers
|
||||
irClass.origin = SERIALIZATION_PLUGIN_ORIGIN
|
||||
}
|
||||
irClass.addDefaultConstructorIfAbsent(context)
|
||||
irClass.addDefaultConstructorBodyIfAbsent(context)
|
||||
irClass.patchDeclarationParents(irClass.parent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// IGNORE_BACKEND_K2: JVM_IR
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// WITH_STDLIB
|
||||
|
||||
// FILE: common.kt
|
||||
|
||||
package foo
|
||||
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@Serializable
|
||||
expect class Expected {
|
||||
companion object { fun factoryMethod(): Expected }
|
||||
}
|
||||
|
||||
// FILE: jvm.kt
|
||||
|
||||
package foo
|
||||
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@Serializable
|
||||
actual class Expected {
|
||||
actual companion object { actual fun factoryMethod(): Expected = Expected() }
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val b = Expected.factoryMethod()
|
||||
if (b !is Expected) return "Incorrect factory method"
|
||||
val desc = Expected.serializer().descriptor
|
||||
if (desc.toString() != "foo.Expected()") return "Incorrect descriptor $desc"
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -57,6 +57,12 @@ public class SerializationFirBlackBoxTestGenerated extends AbstractSerialization
|
||||
runTest("plugins/kotlinx-serialization/testData/boxIr/enumsAreCached.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectActual.kt")
|
||||
public void testExpectActual() throws Exception {
|
||||
runTest("plugins/kotlinx-serialization/testData/boxIr/expectActual.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalSerialierJava.kt")
|
||||
public void testExternalSerialierJava() throws Exception {
|
||||
|
||||
+6
@@ -55,6 +55,12 @@ public class SerializationIrBoxTestGenerated extends AbstractSerializationIrBoxT
|
||||
runTest("plugins/kotlinx-serialization/testData/boxIr/enumsAreCached.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectActual.kt")
|
||||
public void testExpectActual() throws Exception {
|
||||
runTest("plugins/kotlinx-serialization/testData/boxIr/expectActual.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalSerialierJava.kt")
|
||||
public void testExternalSerialierJava() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user