Skip to content

Commit 596bac8

Browse files
authored
Mention type unsoundness of serializer() in the documentation (#2998)
Fixes #2948
1 parent fee0ab1 commit 596bac8

File tree

1 file changed

+52
-24
lines changed

1 file changed

+52
-24
lines changed

core/commonMain/src/kotlinx/serialization/Serializers.kt

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import kotlin.reflect.*
2323
* This overload works with full type information, including type arguments and nullability,
2424
* and is a recommended way to retrieve a serializer.
2525
* For example, `serializer<List<String?>>()` returns [KSerializer] that is able
26-
* to serialize and deserialize list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
26+
* to serialize and deserialize a list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
2727
*
2828
* Variance of [T]'s type arguments is not used by the serialization and is not taken into account.
2929
* Star projections in [T]'s type arguments are prohibited.
@@ -42,7 +42,7 @@ public inline fun <reified T> serializer(): KSerializer<T> {
4242
* This overload works with full type information, including type arguments and nullability,
4343
* and is a recommended way to retrieve a serializer.
4444
* For example, `serializer<List<String?>>()` returns [KSerializer] that is able
45-
* to serialize and deserialize list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
45+
* to serialize and deserialize a list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
4646
*
4747
* Variance of [T]'s type arguments is not used by the serialization and is not taken into account.
4848
* Star projections in [T]'s type arguments are prohibited.
@@ -60,12 +60,17 @@ public inline fun <reified T> SerializersModule.serializer(): KSerializer<T> {
6060
*
6161
* This overload works with full type information, including type arguments and nullability,
6262
* and is a recommended way to retrieve a serializer.
63-
* For example, `serializer<typeOf<List<String?>>>()` returns [KSerializer] that is able
64-
* to serialize and deserialize list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
63+
* For example, `serializer(typeOf<List<String?>>())` returns [KSerializer] that is able
64+
* to serialize and deserialize a list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
6565
*
6666
* Variance of [type]'s type arguments is not used by the serialization and is not taken into account.
6767
* Star projections in [type]'s arguments are prohibited.
6868
*
69+
* **Pitfall**: the returned serializer may return incorrect results or throw a [ClassCastException] if it receives
70+
* a value that's not a valid instance of the [KType], even though the type allows passing such a value.
71+
* Consider using the `serializer()` overload accepting a type argument (for example, `serializer<List<String>>()`),
72+
* which returns the serializer with the correct type.
73+
*
6974
* @throws SerializationException if serializer cannot be created (provided [type] or its type argument is not serializable).
7075
* @throws IllegalArgumentException if any of [type]'s arguments contains star projection
7176
*/
@@ -80,11 +85,16 @@ public fun serializer(type: KType): KSerializer<Any?> = EmptySerializersModule()
8085
* The nullability of returned serializer is specified using the [isNullable].
8186
*
8287
* Note that it is impossible to create an array serializer with this method,
83-
* as array serializer needs additional information: type token for an element type.
88+
* as an array serializer needs additional information: type token for an element type.
8489
* To create array serializer, use overload with [KType] or [ArraySerializer] directly.
8590
*
8691
* Caching on JVM platform is disabled for this function, so it may work slower than an overload with [KType].
8792
*
93+
* **Pitfall**: the returned serializer may return incorrect results or throw a [ClassCastException] if it receives
94+
* a value that's not a valid instance of the [KClass], even though the type allows passing such a value.
95+
* Consider using the `serializer()` overload accepting a type argument (for example, `serializer<List<String>>()`),
96+
* which returns the serializer with the correct type.
97+
*
8898
* @throws SerializationException if serializer cannot be created (provided [kClass] or its type argument is not serializable)
8999
* @throws SerializationException if [kClass] is a `kotlin.Array`
90100
* @throws SerializationException if size of [typeArgumentsSerializers] does not match the expected generic parameters count
@@ -102,12 +112,15 @@ public fun serializer(
102112
*
103113
* This overload works with full type information, including type arguments and nullability,
104114
* and is a recommended way to retrieve a serializer.
105-
* For example, `serializerOrNull<typeOf<List<String?>>>()` returns [KSerializer] that is able
106-
* to serialize and deserialize list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
115+
* For example, `serializerOrNull(typeOf<List<String?>>())` returns [KSerializer] that is able
116+
* to serialize and deserialize a list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
107117
*
108118
* Variance of [type]'s arguments is not used by the serialization and is not taken into account.
109119
* Star projections in [type]'s arguments are prohibited.
110120
*
121+
* **Pitfall**: the returned serializer may return incorrect results or throw a [ClassCastException] if it receives
122+
* a value that's not a valid instance of the [KType], even though the type allows passing such a value.
123+
*
111124
* @return [KSerializer] for the given [type] or `null` if serializer cannot be created (given [type] or its type argument is not serializable).
112125
* @throws IllegalArgumentException if any of [type]'s arguments contains star projection
113126
*/
@@ -120,12 +133,18 @@ public fun serializerOrNull(type: KType): KSerializer<Any?>? = EmptySerializersM
120133
*
121134
* This overload works with full type information, including type arguments and nullability,
122135
* and is a recommended way to retrieve a serializer.
123-
* For example, `serializer<typeOf<List<String?>>>()` returns [KSerializer] that is able
124-
* to serialize and deserialize list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
136+
* For example, `serializer(typeOf<List<String?>>())` returns [KSerializer] that is able
137+
* to serialize and deserialize a list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
125138
*
126139
* Variance of [type]'s arguments is not used by the serialization and is not taken into account.
127140
* Star projections in [type]'s arguments are prohibited.
128141
*
142+
* **Pitfall**: the returned serializer may return incorrect results or throw a [ClassCastException] if it receives
143+
* a value that's not a valid instance of the [KType], even though the type allows passing such a value.
144+
* Consider using the `serializer()` overload accepting a type argument
145+
* (for example, `module.serializer<List<String>>()`),
146+
* which returns the serializer with the correct type.
147+
*
129148
* @throws SerializationException if serializer cannot be created (provided [type] or its type argument is not serializable and is not registered in [this] module).
130149
* @throws IllegalArgumentException if any of [type]'s arguments contains star projection
131150
*/
@@ -143,11 +162,17 @@ public fun SerializersModule.serializer(type: KType): KSerializer<Any?> =
143162
* The nullability of returned serializer is specified using the [isNullable].
144163
*
145164
* Note that it is impossible to create an array serializer with this method,
146-
* as array serializer needs additional information: type token for an element type.
165+
* as an array serializer needs additional information: type token for an element type.
147166
* To create array serializer, use overload with [KType] or [ArraySerializer] directly.
148167
*
149168
* Caching on JVM platform is disabled for this function, so it may work slower than an overload with [KType].
150169
*
170+
* **Pitfall**: the returned serializer may return incorrect results or throw a [ClassCastException] if it receives
171+
* a value that's not a valid instance of the [KClass], even though the type allows passing such a value.
172+
* Consider using the `serializer()` overload accepting a type argument
173+
* (for example, `module.serializer<List<String>>()`),
174+
* which returns the serializer with the correct type.
175+
*
151176
* @throws SerializationException if serializer cannot be created (provided [kClass] or its type argument is not serializable and is not registered in [this] module)
152177
* @throws SerializationException if [kClass] is a `kotlin.Array`
153178
* @throws SerializationException if size of [typeArgumentsSerializers] does not match the expected generic parameters count
@@ -168,12 +193,15 @@ public fun SerializersModule.serializer(
168193
*
169194
* This overload works with full type information, including type arguments and nullability,
170195
* and is a recommended way to retrieve a serializer.
171-
* For example, `serializerOrNull<typeOf<List<String?>>>()` returns [KSerializer] that is able
172-
* to serialize and deserialize list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
196+
* For example, `serializerOrNull(typeOf<List<String?>>())` returns [KSerializer] that is able
197+
* to serialize and deserialize a list of nullable strings — i.e. `ListSerializer(String.serializer().nullable)`.
173198
*
174199
* Variance of [type]'s arguments is not used by the serialization and is not taken into account.
175200
* Star projections in [type]'s arguments are prohibited.
176201
*
202+
* **Pitfall**: the returned serializer may return incorrect results or throw a [ClassCastException] if it receives
203+
* a value that's not a valid instance of the [KType], even though the type allows passing such a value.
204+
*
177205
* @return [KSerializer] for the given [type] or `null` if serializer cannot be created (given [type] or its type argument is not serializable and is not registered in [this] module).
178206
* @throws IllegalArgumentException if any of [type]'s arguments contains star projection
179207
*/
@@ -276,24 +304,24 @@ internal fun SerializersModule.serializersForParameters(
276304
* The given class must be annotated with [Serializable] or be one of the built-in types.
277305
*
278306
* This method uses platform-specific reflection available for the given erased `KClass`
279-
* and is not recommended to use this method for anything, but last-ditch resort, e.g.
280-
* when all type info is lost, your application has crashed and it is the final attempt to log or send some serializable data.
307+
* and is not recommended to use this method for anything, but last-ditch resort, e.g.,
308+
* when all type info is lost, your application has crashed, and it is the final attempt to log or send some serializable data.
281309
*
282310
* The recommended way to retrieve the serializer is inline [serializer] function and [`serializer(KType)`][serializer]
283311
*
284312
* This API is not guaranteed to work consistently across different platforms or
285-
* to work in cases that slightly differ from "plain @Serializable class" and have platform and reflection specific limitations.
313+
* to work in cases that slightly differ from "plain @Serializable class" and have platform- and reflection-specific limitations.
286314
*
287315
* ### Constraints
288316
* This paragraph explains known (but not all!) constraints of the `serializer()` implementation.
289-
* Please note that they are not bugs, but implementation restrictions that we cannot workaround.
317+
* Please note that they are not bugs but implementation restrictions that we cannot work around.
290318
*
291319
* * This method may behave differently on JVM, JS and Native because of runtime reflection differences
292320
* * Serializers for classes with generic parameters are ignored by this method
293-
* * External serializers generated with `Serializer(forClass = )` are not lookuped consistently
294-
* * Serializers for classes with named companion objects are not lookuped consistently
321+
* * External serializers generated with `Serializer(forClass = )` are not looked up consistently
322+
* * Serializers for classes with named companion objects are not looked up consistently
295323
*
296-
* @throws SerializationException if serializer can't be found.
324+
* @throws SerializationException if the serializer can't be found.
297325
*/
298326
@InternalSerializationApi
299327
public fun <T : Any> KClass<T>.serializer(): KSerializer<T> = serializerOrNull() ?: serializerNotRegistered()
@@ -302,20 +330,20 @@ public fun <T : Any> KClass<T>.serializer(): KSerializer<T> = serializerOrNull()
302330
* Retrieves a [KSerializer] for the given [KClass] or returns `null` if none is found.
303331
* The given class must be annotated with [Serializable] or be one of the built-in types.
304332
* This method uses platform-specific reflection available for the given erased `KClass`
305-
* and it is not recommended to use this method for anything, but last-ditch resort, e.g.
306-
* when all type info is lost, your application has crashed and it is the final attempt to log or send some serializable data.
333+
* and it is not recommended to use this method for anything, but last-ditch resort, e.g.,
334+
* when all type info is lost, your application has crashed, and it is the final attempt to log or send some serializable data.
307335
*
308336
* This API is not guaranteed to work consistently across different platforms or
309337
* to work in cases that slightly differ from "plain @Serializable class".
310338
*
311339
* ### Constraints
312340
* This paragraph explains known (but not all!) constraints of the `serializerOrNull()` implementation.
313-
* Please note that they are not bugs, but implementation restrictions that we cannot workaround.
341+
* Please note that they are not bugs but implementation restrictions that we cannot work around.
314342
*
315343
* * This method may behave differently on JVM, JS and Native because of runtime reflection differences
316344
* * Serializers for classes with generic parameters are ignored by this method
317-
* * External serializers generated with `Serializer(forClass = )` are not lookuped consistently
318-
* * Serializers for classes with named companion objects are not lookuped consistently
345+
* * External serializers generated with `Serializer(forClass = )` are not looked up consistently
346+
* * Serializers for classes with named companion objects are not looked up consistently
319347
*/
320348
@InternalSerializationApi
321349
public fun <T : Any> KClass<T>.serializerOrNull(): KSerializer<T>? =

0 commit comments

Comments
 (0)