Kotlin / kotlinx.serialization

Kotlin multiplatform / multi-format serialization
Apache License 2.0
5.34k stars 618 forks source link

Class PetDbo have constructor parameters which are not properties and therefore it is not serializable automatically #2246

Open nacyolsa opened 1 year ago

nacyolsa commented 1 year ago

Describe the bug I'm getting a compiler exception when I add a new field to my class.

java.lang.IllegalStateException: Class PetDbo have constructor parameters which are not properties and therefore it is not serializable automatically
    at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen.checkSerializability(SerializerCodegen.kt:28)
    at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen.generateSerializableClassPropertyIfNeeded(SerializerCodegen.kt:101)
    at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen.generate(SerializerCodegen.kt:34)
    at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator$Companion.generate(SerializerIrGenerator.kt:573)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializerClassLowering.lower(SerializationLoweringExtension.kt:60)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:36)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitClass(IrElementVisitorVoid.kt:111)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:30)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:30)
    at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:64)
    at org.jetbrains.kotlin.ir.declarations.IrFile.acceptChildren(IrFile.kt:36)
    at org.jetbrains.kotlin.ir.visitors.IrVisitorsKt.acceptChildrenVoid(IrVisitors.kt:15)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitElement(SerializationLoweringExtension.kt:32)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitPackageFragment(IrElementVisitorVoid.kt:190)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitPackageFragment(SerializationLoweringExtension.kt:30)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitFile(IrElementVisitorVoid.kt:200)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:30)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitFile(IrElementVisitorVoid.kt:198)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:30)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:30)
    at org.jetbrains.kotlin.ir.declarations.IrFile.accept(IrFile.kt:30)
    at org.jetbrains.kotlin.ir.visitors.IrVisitorsKt.acceptVoid(IrVisitors.kt:11)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt.runOnFileInOrder(SerializationLoweringExtension.kt:30)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtension.generate(SerializationLoweringExtension.kt:78)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr$lambda$1(JvmIrCodegenFactory.kt:183)
    at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:99)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:215)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:53)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.convertToIr(KotlinToJVMBytecodeCompiler.kt:230)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:113)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:58)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:158)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:53)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:99)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:47)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
    at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:475)
    at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:125)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:373)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally$default(IncrementalCompilerRunner.kt:318)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:180)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:79)
    at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:625)
    at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:101)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1746)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)

To Reproduce

interface SchemaVersionable {}

@Serializable
sealed interface PetDboSchema : SchemaVersionable

@OptIn(ExperimentalSerializationApi::class)
@Serializer(forClass = PetDbo::class)
object PetDboGeneratedSerializer : KSerializer<PetDbo>

@OptIn(ExperimentalSerializationApi::class)
@Serializer(forClass = PetDbo::class)
object PetDboSerializer : KSerializer<PetDbo> {

    override fun deserialize(decoder: Decoder): PetDbo =
        decoder.customExtensionDeserializationFunction(deserializer =  PetDboSchemaDeserializer)

}

object PetDboSchemaDeserializer {

   fun getDeserializer(schemaVersion: Int): KSerializer<out SchemaVersionable>? =
         //...
           PetDboGeneratedSerializer
}

@Serializable(with = PetDboSerializer::class)
data class PetDbo(
    @SerialName("_id")
    @Serializable(with = UUIDSerializer::class)
    val id: UUID,
    val field1: String,
    val field2: String,
): PetDboSchema

PetDbo it's simplified version of my class but I believe it will be sufficient to reproduce the issue. Adding a new field val aaa: String = "asd" to PetDbo should trigger this exception after running gradle build. Exception disappear when I clean project.

Expected behavior

Exception should not happen.

Environment

sandwwraith commented 1 year ago

I've checked with Kotlin 1.8.10, and there's no such error. Can you check it with the 1.8.10 or 1.8.20 Kotlin version, please?

nacyolsa commented 1 year ago

I checked with Kotlin 1.8.20. Looks like issue doesn't occur but for more tests I need to wait for permanent Kotlin upgrade in my project.