Configurate icon indicating copy to clipboard operation
Configurate copied to clipboard

TypeToken interprets Kotlin type variance wrongly

Open NichtStudioCode opened this issue 1 year ago • 0 comments

Since Kotlin's type variance works different, there are some issues when using io.leangen.geantyref.TypeToken:

In Java, this works as expected:

System.out.println(new TypeToken<Set<String>>() {}.getType()); // java.util.Set<java.lang.String>

In Kotlin, this interpreted wrongly:

println(object : TypeToken<Set<String>>() {}.type) // java.util.Set<? extends java.lang.String>

This can then lead to unexpected exceptions, as Configurate won't find serializes for type ? extends String:

// import org.spongepowered.configurate.kotlin.extensions.get
println(root.node("list").get<Set<String>>())
Exception in thread "main" org.spongepowered.configurate.serialize.SerializationException: [list] of type ? extends java.lang.String: No applicable type serializer for type
	at org.spongepowered.configurate.serialize.AbstractListChildSerializer.deserialize(AbstractListChildSerializer.java:50)
	at org.spongepowered.configurate.AbstractConfigurationNode.get(AbstractConfigurationNode.java:151)
	at org.spongepowered.configurate.ConfigurationNode.get(ConfigurationNode.java:458)
	at org.example.ConfigurateTestKt.main(ConfigurateTest.kt:70)
	at org.example.ConfigurateTestKt.main(ConfigurateTest.kt)

The reason for this is that Kotlin has declaration-site variance and the immutable kotlin.collections.Set is covariant (public interface Set<out E> : Collection<E>), which translates to java.util.Set<? extends java.lang.String> at runtime. The easiest way to fix this would be to use Kotlin's built-in typeOf in Configurate's Kotlin extension functions. As an additional benefit, this also removes the overhead of tons of anonymous classes.

println(typeOf<Set<String>>().javaType) // java.util.Set<java.lang.String>

NichtStudioCode avatar Jul 21 '23 08:07 NichtStudioCode