Skip to content

Boxed primitives for value classes in structures #2738

Open
@Chuckame

Description

@Chuckame

Describe the bug
Given a serializable data class having a value class wrapping a primitive type, the field is serialized using .encodeSerializableElement(serialDesc, 0, (SerializationStrategy)myData.$serializer.INSTANCE, myData.box-impl(self.value)) instead of encodeInlineElement(serialDesc, 0).encodeInt(self.value), forcing primitive values to be boxed, and also doesn't follow the expected as said in the docs:

    /**
     * Namely, for the `@Serializable @JvmInline value class MyInt(val my: Int)`,
     * and `@Serializable class MyData(val myInt: MyInt)` the following sequence is used:
     * ```
     * thisEncoder.encodeInlineElement(MyData.serializer.descriptor, 0).encodeInt(my)
     * ```
     *
     * This method provides an opportunity for the optimization to avoid boxing of a carried value [...]
     * ```
     */
    public fun encodeInlineElement(
        descriptor: SerialDescriptor,
        index: Int
    ): Encoder

To Reproduce
Check the bytecode generated from this code:

    @Serializable
    data class Structure(
        val primitiveField: BooleanValue,
    )

    @Serializable
    @JvmInline
    value class BooleanValue(val value: Boolean)

And here is the generated serializer (only the interesting part) retrieved using Kotlin bytecode IDEA tooling:

output.encodeSerializableElement(serialDesc, 0, (SerializationStrategy)ReproduceBug.BooleanValue.$serializer.INSTANCE, ReproduceBug.BooleanValue.box-impl(self.primitiveField));

Expected behavior
Should call encodeInlineElement and generate the following (not sure for the nullable value class' field):

output.encodeInlineElement(serialDesc, 0, (SerializationStrategy)ReproduceBug.BooleanValue.$serializer.INSTANCE).encodeBoolean(self.primitiveField);

Environment

  • Kotlin version: 1.9.22 & 2.0.0 & 2.0.20
  • Library version: 1.7.0+ (not tested with previous versions)
  • Kotlin platforms: jvm (and surely the other platforms, but not tested)
  • Gradle version: 8.7

EDIT: shortened the description

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions