On inference of existential types

Guanpeng Xu <[email protected]> Fri, 20 May 2016 23:25:04 -0700 (PDT)
Newsgroups gmane.comp.lang.scala
Message-ID <[email protected]>
Dear group,

Suppose I have a Java class Q defined as this:

public class Q<T> {

    public Q() {}
    public Q(Q<T> q) {}

    public static <T> Q<T> f(Q<? extends T>[] qs) {
        throw new UnsupportedOperationException();
    }

    public static <T> Q<T> g(Q<? extends Q<? extends T>> q) {
        throw new UnsupportedOperationException();
    }
}

Now, the following Scala program cannot be compiled:

object C {

    val qs: Array[Q[_ <: Int]] = Array.fill(1)(new Q())
    val a = Q.f(qs)

    val q: Q[_ <: Q[_ <: Int]] = new Q(new Q())
    val b = Q.g(q)
}

The errors are

[error] Q.scala:6: no type parameters for method f: (x$1: Array[rxtest.Q[_ 
<: T]])rxtest.Q[T] exist so that it can be applied to arguments 
(Array[rxtest.Q[_ <: Int]])
[error]  --- because ---
[error] argument expression's type is not compatible with formal parameter 
type;
[error]  found   : Array[rxtest.Q[_ <: Int]]
[error]  required: Array[rxtest.Q[_ <: ?T]]
[error]     val a = Q.f(qs)
[error]               ^
[error] Q.scala:6: type mismatch;
[error]  found   : Array[rxtest.Q[_ <: Int]]
[error]  required: Array[rxtest.Q[_ <: T]]
[error]     val a = Q.f(qs)
[error]                 ^
[error] Q.scala:9: no type parameters for method g: (x$1: rxtest.Q[_ <: 
rxtest.Q[_ <: T]])rxtest.Q[T] exist so that it can be applied to arguments 
(rxtest.Q[_$2])
[error]  --- because ---
[error] argument expression's type is not compatible with formal parameter 
type;
[error]  found   : rxtest.Q[_$2] where type _$2 <: rxtest.Q[_ <: Int]
[error]  required: rxtest.Q[_ <: rxtest.Q[_ <: ?T]]
[error]     val b = Q.g(q)
[error]               ^
[error] Q.scala:9: type mismatch;
[error]  found   : rxtest.Q[_$2] where type _$2 <: rxtest.Q[_ <: Int]
[error]  required: rxtest.Q[_ <: rxtest.Q[_ <: T]]
[error]     val b = Q.g(q)
[error]                 ^
[error] four errors found

I expected T in the two calls to be inferred as Int, but something 
prevented that.  Is this due to a bad design of the Java program, or some 
limitation of the type inferer of Scala?

(The example above is simplified from the real world design of RxJava.  I 
asked a question 
<http://stackoverflow.com/questions/36623018/calling-overloaded-rxjava-functions-from-scala> 
on StackOverflow.  My intention was to understand the Scala language and I 
was not satisfied with the answer there.)

Best regards,
Guanpeng Xu

-- 
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.