Skip to content

TypeToken interprets Kotlin type variance wrongly #420

Description

@NichtStudioCode

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>

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions