Kotlin compiler's type inference can't choose which method to call (ambiguity with generic types)

Question

So, I have some Java methods with these signatures (removed annotations and code body for the sake of simplicity):

public class JavaClass {
  public static <E extends CharSequence> E join(E... array) { ... }
  public static <E extends CharSequence> E join(CharSequence separator, E... array) { ... }
}

And I have some code in Kotlin, which calls the 'join' method:

class KtClass {
    fun test(vararg array: String) {
        JavaClass.join(*array)
    }
}

So far so good; it will spread the varargs and call the former method signature. Okie dokie!

The problem comes if, for example, I want to call the latter method signature, with a 'separator' argument:

class KtClass {
    fun test(vararg array: String) {
        JavaClass.join("<br>", *array)
    }
}

This code won't compile. The compiler can't get to decide which method to call. The error:

Error:(5, 13) Kotlin: Cannot choose among the following candidates without completing type inference: public open fun join(vararg array: String!): String! defined in JavaClass public open fun join(separator: CharSequence!, vararg array: String!): String! defined in JavaClass

I can't even name the arguments because Kotlin doesn't let argument naming for non-Kotlin functions.

EDIT: Replaced the E generic type parameter with plain String references in the Java method headers, and it worked! So I guess this to be an incompatibility of type inference with generic types or something like that?



I'm pretty sure this has to be something with the spread operator (*). But I can't pass the varargs parameter array to the join function if I don't use it.

How can I solve this without touching the Java code?

YES, I KNOW that there is Array.joinToString extension function, but this would solve only this particular case. I need to know a generic solution.


Show source
| generics   | kotlin   | overloading   | method-overloading   | kotlin-interop   2017-01-05 20:01 2 Answers

Answers to Kotlin compiler&#39;s type inference can&#39;t choose which method to call (ambiguity with generic types) ( 2 )

  1. 2017-01-05 20:01

    I don't think that's Kotlin specific. The problem is that the generic argument, E is of type CharSequence so your call becomes something like join("separator", "word1", "word2") which is, indeed, ambiguous since the first argument, of type E == CharSequence is the same as the type of the other args.

  2. 2017-01-05 21:01

    It looks like you will need to create a helper class in Java to bridge the interop issue. e.g.:

    public class JavaClassInterop {
        public static <E extends CharSequence> E joinSeparatedBy(CharSequence separator,
                                                                 E... array) {
            return JavaClass.join(separator, array);
        }
    }
    

    Then you can call both:

    import JavaClass.join
    import JavaClassInterop.joinSeparatedBy
    
    fun main(args: Array<String>) {
        join(*args)
        joinSeparatedBy("<br>", *args)
    }
    

Leave a reply to - Kotlin compiler's type inference can't choose which method to call (ambiguity with generic types)

◀ Go back