Type variable as wildcard bound

Zhong Yu zhong.j.yu at gmail.com
Thu Nov 17 08:32:47 PST 2011

On Thu, Nov 17, 2011 at 6:43 AM, Maurizio Cimadamore
<maurizio.cimadamore at oracle.com> wrote:
> On 15/11/11 23:23, Zhong Yu wrote:
> Hi team, I don't understand the behavior of javac7 u2 b11 on the following
> code:
>    class G<N extends Number> {}
>    <T> void f1(G<? extends T> k){} //error. why?
>    <T> void f2(G<? super   T> k){} //ok. why?
> With capture conversion applied, in f1, we have upper bound T&Number,
> lower bound null. I don't see any problem here, even if for some T,
> T&Number=null. Is the combination of T&Number illegal?
> In f2, we have upper bound Number, lower bound T. Since it's not true
> that T<:Number, I don't see why this should compile.
> The failure you are seeing is caused by the following statement in JLS
> section 5.1.10:
> "If Ti is a wildcard type argument of the form ? extends Bi, then Si is a
> fresh type variable whose upper bound is glb(Bi, Ui[A1 := S1, ...,
> An := Sn]) and whose lower bound is the null type, where glb(V1,...
> ,Vm) is V1& ... & Vm. It is a compile-time error if for any two classes (not
> interfaces) Vi and Vj,Vi is not a subclass of Vj or vice versa."
> Historically, javac has always interpreted the underlined text very strictly
> - meaning that glb(T, Number) where T is a type-variable (whose bound is
> Object) does not exist, as neither T <: Number nor Number <: T. As such, the
> capture conversion for G<? extends T> does not exist.
> While Javac 1.6 didn't complain about that specific code, it still ended up
> in calculating an erroneous glb - which then led to bad programs like the
> following to compile without errors:
> class G<N extends Number> {
>    private N n;
>    G(N n) { this.n = n; }
>    N g() { return n; };
> }
> class Test {
>    static <T> void f1(G<? extends T> k){ String s = k.g(); }
>    public static void main(String[] args) {
>       Test.f1(new G<Integer>(1)); //throws CCE at runtime!!!
>    }
> }
> In JDK 7 we made these error manifests, so that the glb computation failure
> is now explicit. This way no unsound programs will be accepted (and, as a
> side-effect, we got rid of a number of javac crashes related to the fact
> that javac needed to hanlde this erroneous captured type).
> We will consider as to whether the above JLS paragraph needs rewording and,

Thanks. My understanding of the clause was that it doesn't affect type
variables; also it's redundant as the restriction is already covered
in 4.9.

4.9 mentions "direct superclass Ck", but Ck can be an array or a final class.

Zhong Yu

> perhaps, to be loosened, in order to allow glb(T, Number) to yield T &
> Number.
> Thanks
> Maurizio
> Both f1() and f2() compiles under javac 6.
> cheers,
> Zhong Yu

More information about the compiler-dev mailing list