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