Skip to content

[KT-84952]Generate explicit typeParametersSerializers() for all GeneratedSerializer implementations#5744

Open
lamaxama wants to merge 1 commit intoJetBrains:masterfrom
lamaxama:fix/serializer
Open

[KT-84952]Generate explicit typeParametersSerializers() for all GeneratedSerializer implementations#5744
lamaxama wants to merge 1 commit intoJetBrains:masterfrom
lamaxama:fix/serializer

Conversation

@lamaxama
Copy link

@lamaxama lamaxama commented Mar 13, 2026

Fixes: #KT-84952

Problem

Starting with kotlinx.serialization 1.8.0, the library switched to "all-compatibility" mode which generates Java 8 default method implementations in interfaces. This causes Android-specific runtime failures when the serialization runtime is used as a compileOnly dependency.

For serializable classes without type parameters, the generated $serializer class now calls:

return GeneratedSerializer.$-CC.$default$typeParametersSerializers(this);

The GeneratedSerializer$-CC class is generated by d8 desugaring during Android APK compilation from the interface's default methods. However, when kotlinx.serialization is declared as compileOnly:

  1. The serialization library is excluded from the final APK
  2. The $-CC companion class cannot be generated by d8 because the interface definitions are not available in the compilation classpath
  3. Runtime fails with NoClassDefFoundError: GeneratedSerializer$-CC

This affects Android plugin/extension architectures where:

  • Extensions are compiled with compileOnly dependency on serialization
  • Host app provides the serialization runtime at load time
  • d8 desugaring cannot generate the required $-CC class

Real-world Impact

See keiyoushi/extensions-source#12962 for a detailed analysis and real-world case where this issue blocked upgrading to Kotlin 2.x.

Solution

Modify the Kotlin serialization compiler plugin (K2/FIR) to always generate an explicit typeParametersSerializers() method implementation for all $serializer classes that implement GeneratedSerializer, regardless of whether the class has type parameters.

Before this change

For classes without type parameters, no typeParametersSerializers() method was generated. The class relied on the interface default implementation:

// Generated $serializer class - no typeParametersSerializers method
public final class Foo$$serializer : GeneratedSerializer<Foo> {
    // Relies on GeneratedSerializer.typeParametersSerializers() default implementation
}

After this change

All $serializer classes explicitly implement the method:

// For classes without type parameters - returns empty array directly
public final class Foo$$serializer : GeneratedSerializer<Foo> {
    public override fun typeParametersSerializers(): Array<KSerializer<*>> = arrayOf()
}

// For classes with type parameters - returns the type parameter serializers
public final class GenericBox$$serializer<T, V> : GeneratedSerializer<GenericBox<T, V>> {
    public override fun typeParametersSerializers(): Array<KSerializer<*>> = arrayOf(typeSerial0, typeSerial1)
}

@kotlin-safe-merge
Copy link

Code Owners

Rule Owners Approval
/​plugins/​kotlinx-​serialization/​ @sandwwraith, @shanshin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant