Type variable as wildcard bound
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Nov 17 04:43:45 PST 2011
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/T_i /is a wildcard type argument of the form|? extends|/B_i /,
then/S_i /is a fresh type variable whose upper bound is/glb(B_i /,/U_i
[A_1 /:=/S_1 , ..., A_n /:=/S_n ]/) and whose lower bound is the null
type, where/glb(V_1 ,... ,V_m )/is/V_1 & ... & V_m /. _It is a
compile-time error if for any two classes (not interfaces)__/V_i
/and/V_j ,V_i /is not a subclass of/V_j /__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, 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20111117/fd723b85/attachment.html
More information about the compiler-dev
mailing list