[POSSIBLE BUG] generic method overload ambiguity

Hi, I’m using Kotlin 1.2.31 in IDEA 2018.1-1, both are the latest version as of writing


I’m aware of many workarounds to this, like using different arg names, but I’m wondering if this is a BUG or not. If not, may I ask why it’s designed like this?

code here for easier copy and experiment:

class Instance<in K,in V:Number>{
    fun method(arg:K)=Unit
    fun method(arg:V)=Unit
}
fun main(args:Array<String>){
    Instance<Any,Int>().method(1 as Number)
    Instance<Any,Int>().method(1)
}

I don’t think different arg names would help :wink:
Interesting problem. Even more interesting is that if you remove the second call to method you can see that
Instance<Any, Int>().method(1 as Number) calls the method taking Any as an argument.

Yes I think this is a bug. I guess both parts of it. I would think that you should be able to call the method just passing an int and I would definitely expect it to call the version taking a Number as an argument.

You should create an issue here: https://youtrack.jetbrains.com/issues/KT

That is because of the way that JVM generics work using type erasure. Generic type checking is all at compile time and any generic variable or parameter at runtime is just Object (in Java) or Any in Kotlin. So both generated methods would both have the same type of parameter. Even if you did not have this limitation what do you expect the compiler to do for an Instance<Number, Number>?

Kotlin does give you a way to do it with the downside that if you are calling from Java the method names will be different. See https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#handling-signature-clashes-with-jvmname

Guess you don’t know this :stuck_out_tongue_winking_eye:

Actually I don’t think this is the case, type erasure, if I remember it correctly, erases to the upper bound. So there are two different methods, one method(Any) and one method(Number). And Instance<Number,Number> is just a Instance<Any,Number> at runtime. At compile-time, I think Kotlin should be able to distinguish them.

If more people think this is a BUG, I’ll file an issue