Inconsistent type parameters : How to implements generic interfaces with differents types

Hello Kotliners, I face a problem with type erasure, is there a way to implements implementation of same generic interface with different types ?

fun main() {
   val foo = Foo()
   println(foo[0])
   println(foo[0L])
}

interface Index<Idx, Type> {
   operator fun get(i: Idx): Type
}

interface IntIndex<Type> {
   operator fun get(i: Int): Type
} 

interface LongIndex<Type> {
   operator fun get(i: Long): Type
}

// class Foo: Index<Int, String>, Index<Long, String> <- This is forbidden
class Foo: IntIndex<String>, LongIndex<String> { // This is allowed
   override fun get(i: Int) = "TODO for Int"
   override fun get(i: Long) = "TODO for Long"
}

Sounds like a JVM restriction – both Index<Int, String> and Index<Long, String> represent the same nominal type. So a supertype declaration can only contain one of them; Whereas IntIndex and LongIndex are treated as different nominal types.

1 Like

Thanks for the response :slightly_smiling_face:. Anyone knows if the Valhalla project will “fix” this problem ?

No, it won’t. Valhalla has nothing to do with generics. Actually, in Kotlin you can work around type erasure if you are using compile-time dispatch. Like this:

fun doSomething(list: List<Double>){}
@JvmName("doSomethingWithList")
fun doSomething(list: List<Int>){}

fun main(){
    doSomething(listOf(1,2,3))
}

Correction. Part of Valhalla IS about generics, especially reified generics for value-types. But it is not about type erasure.

Yes that’s why I believe that it would be possible to implements two types in Kotlin as the compiler can perform non valid Java dispatch. By the way thanks for the response