kotlinx.serialization: Unable to get inline class serialized
I tried to serialize an inlined class. The class is implemented in the commons project of a MPP. The compiler arg “-XXLanguage:+InlineClasses” is defined in the JVM and JS project.
Class:
@Serializable
inline class DeviceId(val value: String) {
override fun toString(): String = value
}
And get the following exception:
The root cause was thrown at: ImplementationBodyCodegen.java:863
at org.jetbrains.kotlin.codegen.CompilationErrorHandler.lambda$static$0(CompilationErrorHandler.java:24)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generate(PackageCodegenImpl.java:74)
at org.jetbrains.kotlin.codegen.DefaultCodegenFactory.generatePackage(CodegenFactory.kt:97)
at org.jetbrains.kotlin.codegen.DefaultCodegenFactory.generateModule(CodegenFactory.kt:68)
at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.doGenerateFiles(KotlinCodegenFacade.java:47)
at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:39)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:446)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:142)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:161)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:57)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:96)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:52)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:93)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:362)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:102)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:225)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.access$compileIncrementally(IncrementalCompilerRunner.kt:39)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner$compile$2.invoke(IncrementalCompilerRunner.kt:91)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:103)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.execIncrementalCompiler(CompileServiceImpl.kt:606)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.access$execIncrementalCompiler(CompileServiceImpl.kt:102)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:455)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:102)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:1029)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:102)
at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:1071)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:1028)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:454)
at sun.reflect.GeneratedMethodAccessor103.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassCastException: org.jetbrains.kotlin.codegen.ErasedInlineClassBodyCodegen cannot be cast to org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
at org.jetbrains.kotlin.codegen.ImplementationBodyCodegen.initializeObjects(ImplementationBodyCodegen.java:863)
at org.jetbrains.kotlin.codegen.ImplementationBodyCodegen.generateSyntheticPartsAfterBody(ImplementationBodyCodegen.java:410)
at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:130)
at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:300)
at org.jetbrains.kotlin.codegen.MemberCodegen.genSyntheticClassOrObject(MemberCodegen.java:314)
at org.jetbrains.kotlin.codegen.ClassBodyCodegen.generateBody(ClassBodyCodegen.java:100)
at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:127)
at org.jetbrains.kotlin.codegen.ImplementationBodyCodegen.generateErasedInlineClassIfNeeded(ImplementationBodyCodegen.java:263)
at org.jetbrains.kotlin.codegen.ClassBodyCodegen.generateBody(ClassBodyCodegen.java:85)
at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:127)
at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:300)
at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:284)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateClassOrObject(PackageCodegenImpl.java:161)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateClassesAndObjectsInFile(PackageCodegenImpl.java:86)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateFile(PackageCodegenImpl.java:119)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generate(PackageCodegenImpl.java:66)
... 43 more
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 24
- Comments: 20 (9 by maintainers)
@aviadmini We’re trying to look into it
@DaanVandenBosch @fluidsonic That’s the right point – since the class is inline and have only one property, it is reasonable to serialize it as an underlying value, not as a JSON object. It should be true even if the property of the inline type itself is boxed (in JVM terms).
I can say that we have finished inline classes design in serialization and it’s the next thing on a roadmap after sealed classes serialization, which has been released in 0.14.0.
Inline class serialization is supported in Kotlin 1.5.0
This seems to be a bit more specific: https://youtrack.jetbrains.com/issue/KT-28791
Yes, an annotation would be good too. So by default the inline class would be boxed, with the annotation it would be inlined? Ideally it would be possible to add the annotation to either the inline class itself or the use-site of the inline class (i.e. a property with an inline class as type). If I had to choose one, I’d prefer an annotation on the inline class itself.
One of my use-cases for inline classes is an ID class per entity type. Using a different ID class per entity ensures you can’t pass e.g. a ProductVariantID to a method or constructor that expects a ProductID. Sending big objects with lots of these IDs in boxed form can greatly increase their size. And in e.g. json, the output becomes hard to read.
@sandwwraith any thoughts on this from Jetbrains?
In Kotlin 1.5, unsigned integers have been made stable. #310 has been closed as a duplicate of this issue, so the priority on this should be increased. Otherwise, this library cannot handle stable features of the language.
@JavierSegoviaCordoba Here you go: https://youtrack.jetbrains.com/issue/KT-23338