diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/checkers/FirSerializationPluginClassChecker.kt b/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/checkers/FirSerializationPluginClassChecker.kt index d6a1d173bb2..61da06d92c2 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/checkers/FirSerializationPluginClassChecker.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/checkers/FirSerializationPluginClassChecker.kt @@ -564,14 +564,14 @@ object FirSerializationPluginClassChecker : FirClassChecker() { serializerType: ConeKotlinType, reporter: DiagnosticReporter ) { - val serializerForType = serializerType.serializerForType(session) ?: return + val serializerForType = serializerType.serializerForType(session)?.fullyExpandedType(session) ?: return val declarationTypeClassId = declarationType.classId if (declarationTypeClassId == null || declarationTypeClassId != serializerForType.classId) { reporter.reportOn( source ?: containingClassSymbol.serializableOrMetaAnnotationSource, FirSerializationErrors.SERIALIZER_TYPE_INCOMPATIBLE, - containingClassSymbol.defaultType(), + declarationType, serializerType, serializerForType ) diff --git a/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.fir.kt b/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.fir.kt index dfb57cc907c..c98390929e9 100644 --- a/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.fir.kt +++ b/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.fir.kt @@ -40,3 +40,11 @@ class Foo6(@Serializable(with = NullableBazSerializer::class) val i: Bar?) + +// It is OK to report, because subclasses can't generally be deserialized (as `deserialize()` signature returns base class) +@Serializable +@Suppress("FINAL_UPPER_BOUND") +class Foo8(@Serializable(BarSerializer::class) val b: Br) + +@Serializable +class Foo9(@Serializable(BarSerializer::class) val b: T) diff --git a/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.kt b/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.kt index 19611d0cb4a..615d05a62dc 100644 --- a/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.kt +++ b/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.kt @@ -40,3 +40,11 @@ class Foo6(@Serializable(with = NullableBazSerializer::class) val i: Bar?) + +// It is OK to report, because subclasses can't generally be deserialized (as `deserialize()` signature returns base class) +@Serializable +@Suppress("FINAL_UPPER_BOUND") +class Foo8(@Serializable(BarSerializer::class) val b: Br) + +@Serializable +class Foo9(@Serializable(BarSerializer::class) val b: T) diff --git a/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.fir.kt b/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.fir.kt new file mode 100644 index 00000000000..71a9ac5edff --- /dev/null +++ b/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.fir.kt @@ -0,0 +1,41 @@ +// FIR_DISABLE_LAZY_RESOLVE_CHECKS +// WITH_STDLIB + +// MODULE: lib +// FILE: libtest.kt + +import kotlinx.serialization.* +import java.util.* + +typealias MyDate = java.util.Date + +// MODULE: main(lib) +// FILE: test.kt + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal object MyDateSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("uuid", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder) = TODO() + + override fun serialize( + encoder: Encoder, + value: MyDate + ) = encoder.encodeString(value.toString()) +} + +@Serializable +data class Session( + @Serializable(MyDateSerializer::class) val date: MyDate, + @Serializable(MyDateSerializer::class) val alsoDate: java.util.Date, + // The only difference with FIR is how RENDER_TYPE works: + @Serializable(MyDateSerializer::class) val s: String, + val sl: List<@Serializable(MyDateSerializer::class) String> +) diff --git a/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.kt b/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.kt new file mode 100644 index 00000000000..81d774f89ed --- /dev/null +++ b/plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.kt @@ -0,0 +1,41 @@ +// FIR_DISABLE_LAZY_RESOLVE_CHECKS +// WITH_STDLIB + +// MODULE: lib +// FILE: libtest.kt + +import kotlinx.serialization.* +import java.util.* + +typealias MyDate = java.util.Date + +// MODULE: main(lib) +// FILE: test.kt + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal object MyDateSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("uuid", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder) = TODO() + + override fun serialize( + encoder: Encoder, + value: MyDate + ) = encoder.encodeString(value.toString()) +} + +@Serializable +data class Session( + @Serializable(MyDateSerializer::class) val date: MyDate, + @Serializable(MyDateSerializer::class) val alsoDate: java.util.Date, + // The only difference with FIR is how RENDER_TYPE works: + @Serializable(MyDateSerializer::class) val s: String, + val sl: List<@Serializable(MyDateSerializer::class) String> +) diff --git a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationFirPsiDiagnosticTestGenerated.java b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationFirPsiDiagnosticTestGenerated.java index fa3c76f39ce..24dc0b4f011 100644 --- a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationFirPsiDiagnosticTestGenerated.java +++ b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationFirPsiDiagnosticTestGenerated.java @@ -164,6 +164,12 @@ public class SerializationFirPsiDiagnosticTestGenerated extends AbstractSerializ runTest("plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.kt"); } + @Test + @TestMetadata("SerializerTypeIncompatibleViaTypealias.kt") + public void testSerializerTypeIncompatibleViaTypealias() throws Exception { + runTest("plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.kt"); + } + @Test @TestMetadata("Transients.kt") public void testTransients() throws Exception { diff --git a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationPluginDiagnosticTestGenerated.java b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationPluginDiagnosticTestGenerated.java index b6f2fb9ccd4..dba8544e420 100644 --- a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationPluginDiagnosticTestGenerated.java +++ b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationPluginDiagnosticTestGenerated.java @@ -162,6 +162,12 @@ public class SerializationPluginDiagnosticTestGenerated extends AbstractSerializ runTest("plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.kt"); } + @Test + @TestMetadata("SerializerTypeIncompatibleViaTypealias.kt") + public void testSerializerTypeIncompatibleViaTypealias() throws Exception { + runTest("plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.kt"); + } + @Test @TestMetadata("Transients.kt") public void testTransients() throws Exception {