Open InsanusMokrassar opened 1 month ago
Minimized reproducer:
object Whatever: KSerializer<X> {
override val descriptor: SerialDescriptor
get() = TODO("Not yet implemented")
override fun deserialize(decoder: Decoder): X = TODO("Not yet implemented")
override fun serialize(encoder: Encoder, value: X): Unit = TODO("Not yet implemented")
}
@Serializable(Whatever::class)
sealed class X {
@Serializable(Whatever::class)
companion object : X() {}
}
This code is not very clear IMO, since normally X.serializer()
should return whatever X is serializable with, but in such case it would return what X.Companion
is serializable with. Only the fact that these two serializers are identical saves from confusion.
This code is not very clear IMO, since normally
X.serializer()
should return whatever X is serializable with, but in such case it would return whatX.Companion
is serializable with. Only the fact that these two serializers are identical saves from confusion.
I agree with you, but I do not know how else provide the same serializer for different types when they actually should be serialized by the same way and serializer knows how todo it correctly
Apparently the issue is even more deep:
@Serializable
sealed class Funny {
@Serializable
companion object : Funny() {}
}
@Serializable
class OuterFunny(val f: Funny)
In such a setup, OuterFunny.f
will be serialized completely incorrectly — with a serializer for Funny.Companion
, which always outputs {}
(because it is ObjectSerializer
). It looks like the plugin needs a warning or error diagnostic for that.
Apparently the issue is even more deep:
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE") @Serializable sealed class Funny { @Serializable companion object : Funny() {} } @Serializable class OuterFunny(val f: Funny)
In such a setup,
OuterFunny.f
will be serialized completely incorrectly — with a serializer forFunny.Companion
, which always outputs{}
(because it isObjectSerializer
). It looks like the plugin needs a warning or error diagnostic for that.
Interesting sample... To be honest, here there is problem on the type-related level, not serialization. I would name it puzzler, because of it have unpredictable behaviour in case you do not know the exact mechanism of code parser even without any annotation here.
My samples have the other case: they are using the exact serializer :)
I think about prohibiting the usage of @Serializable
on the companion object if the class is also @Serializable
— because unless the serializers are strictly identical, such code will never work. Would it be hard for you to migrate from a companion object to a regular object, e.g.:
@Serializable(IetfLangSerializer::class)
sealed class Afrikaans : IetfLang() {
override val code: String = "af"
@Serializable(IetfLangSerializer::class)
object Default: Afrikaans()
}
Although it may be possible to write a diagnostic in such a way that if serializers are identical, it is not reported. But I'm not sure.
I think about prohibiting the usage of
@Serializable
on the companion object if the class is also@Serializable
— because unless the serializers are strictly identical, such code will never work. Would it be hard for you to migrate from a companion object to a regular object, e.g.:@Serializable(IetfLangSerializer::class) sealed class Afrikaans : IetfLang() { override val code: String = "af" @Serializable(IetfLangSerializer::class) object Default: Afrikaans() }
Although it may be possible to write a diagnostic in such a way that if serializers are identical, it is not reported. But I'm not sure.
The case here is to use it like:
Afrikaans // here used Companion without region suffix
Afrikaans.NA // specific region
In case I will rewrite all on object Default
it will at least break a lot of API. Besides, it will be less comfortable:
Afrikaans.Default // It is even longer than specifying the region
Afrikaans.NA // specific region
I am upgrading my project up to latest (currently) dependencies like Kotlin 2.0.0 and K/Serialization 1.7.0-RC and faced with the problem that compiler (or serialization plugin) do not see
serializer
in companion object which must have this function when compiling LinuxArm64 targetTo Reproduce
Expected behavior
Program is correctly compiling
Environment