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.IrDelegatingConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
|
||||||
import org.jetbrains.kotlin.ir.util.primaryConstructor
|
import org.jetbrains.kotlin.ir.util.primaryConstructor
|
||||||
|
|
||||||
// TODO KT-53096
|
// TODO KT-53096
|
||||||
@@ -38,9 +37,7 @@ fun IrPluginContext.generateBodyForDefaultConstructor(declaration: IrConstructor
|
|||||||
return irFactory.createBlockBody(-1, -1, listOf(delegatingAnyCall, initializerCall))
|
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.addDefaultConstructorBodyIfAbsent(ctx: IrPluginContext) {
|
||||||
|
val declaration = primaryConstructor ?: return
|
||||||
fun IrClass.addDefaultConstructorIfAbsent(ctx: IrPluginContext) {
|
|
||||||
val declaration = constructors.primary
|
|
||||||
if (declaration.body == null) declaration.body = ctx.generateBodyForDefaultConstructor(declaration)
|
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?
|
internal val List<IrConstructorCall>.serialNameValue: String?
|
||||||
get() = findAnnotation(SerializationAnnotations.serialNameAnnotationFqName)?.getStringConstArgument(0) // @SerialName("foo")
|
get() = findAnnotation(SerializationAnnotations.serialNameAnnotationFqName)?.getStringConstArgument(0) // @SerialName("foo")
|
||||||
|
|
||||||
|
|
||||||
|
val IrClass.primaryConstructorOrFail get() = primaryConstructor ?: error("$this is expected to have a primary constructor")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True — ALWAYS
|
* True — ALWAYS
|
||||||
* False — NEVER
|
* False — NEVER
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ class SerializableCompanionIrGenerator(
|
|||||||
val serializableClass = getSerializableClassByCompanion(companionDescriptor) ?: return
|
val serializableClass = getSerializableClassByCompanion(companionDescriptor) ?: return
|
||||||
if (serializableClass.shouldHaveGeneratedMethodsInCompanion) {
|
if (serializableClass.shouldHaveGeneratedMethodsInCompanion) {
|
||||||
SerializableCompanionIrGenerator(irClass, getSerializableClassByCompanion(irClass)!!, context).generate()
|
SerializableCompanionIrGenerator(irClass, getSerializableClassByCompanion(irClass)!!, context).generate()
|
||||||
irClass.addDefaultConstructorIfAbsent(context)
|
irClass.addDefaultConstructorBodyIfAbsent(context)
|
||||||
irClass.patchDeclarationParents(irClass.parent)
|
irClass.patchDeclarationParents(irClass.parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -199,7 +199,7 @@ open class SerializerIrGenerator(
|
|||||||
fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: IrConstructor) =
|
fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: IrConstructor) =
|
||||||
addFunctionBody(typedConstructorDescriptor) { ctor ->
|
addFunctionBody(typedConstructorDescriptor) { ctor ->
|
||||||
// generate call to primary ctor to init serialClassDesc and super()
|
// generate call to primary ctor to init serialClassDesc and super()
|
||||||
val primaryCtor = irClass.constructors.primary
|
val primaryCtor = irClass.primaryConstructorOrFail
|
||||||
+IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
+IrDelegatingConstructorCallImpl.fromSymbolOwner(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
@@ -518,7 +518,7 @@ open class SerializerIrGenerator(
|
|||||||
|
|
||||||
generateGoldenMaskCheck(bitMasks, properties, localSerialDesc.get())
|
generateGoldenMaskCheck(bitMasks, properties, localSerialDesc.get())
|
||||||
|
|
||||||
val ctor: IrConstructorSymbol = serializableIrClass.constructors.primary.symbol
|
val ctor: IrConstructorSymbol = serializableIrClass.primaryConstructorOrFail.symbol
|
||||||
val params = ctor.owner.valueParameters
|
val params = ctor.owner.valueParameters
|
||||||
|
|
||||||
val variableByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = { vpd ->
|
val variableByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = { vpd ->
|
||||||
@@ -642,7 +642,7 @@ open class SerializerIrGenerator(
|
|||||||
// replace origin only for plugin generated serializers
|
// replace origin only for plugin generated serializers
|
||||||
irClass.origin = SERIALIZATION_PLUGIN_ORIGIN
|
irClass.origin = SERIALIZATION_PLUGIN_ORIGIN
|
||||||
}
|
}
|
||||||
irClass.addDefaultConstructorIfAbsent(context)
|
irClass.addDefaultConstructorBodyIfAbsent(context)
|
||||||
irClass.patchDeclarationParents(irClass.parent)
|
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");
|
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
|
@Test
|
||||||
@TestMetadata("externalSerialierJava.kt")
|
@TestMetadata("externalSerialierJava.kt")
|
||||||
public void testExternalSerialierJava() throws Exception {
|
public void testExternalSerialierJava() throws Exception {
|
||||||
|
|||||||
+6
@@ -55,6 +55,12 @@ public class SerializationIrBoxTestGenerated extends AbstractSerializationIrBoxT
|
|||||||
runTest("plugins/kotlinx-serialization/testData/boxIr/enumsAreCached.kt");
|
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
|
@Test
|
||||||
@TestMetadata("externalSerialierJava.kt")
|
@TestMetadata("externalSerialierJava.kt")
|
||||||
public void testExternalSerialierJava() throws Exception {
|
public void testExternalSerialierJava() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user