Community
Participate
Working Groups
public class Scratch { private Y rawObject = new Y(); public void caller() { method(new X<Y<Z>>(), rawObject); // compile error in javac, unchecked conversion in Eclipse this.<Y<Z>>method(new X<Y<Z>>(), rawObject); // unchecked warning in both } public <T> void method(X<T> x, T t) {} } class X<S> {} class Y<S> {} class Z {} ========================================================== Using Java 1.6u4, tested in Eclipse 3.3.1.1, 3.4 RC4. Eclipse implicitly converts the raw object to a Y<Z> compiles the above with a few unchecked cast warnings. Javac gives the following error: Scratch.java:5: <T>method(X<T>,T) in Scratch cannot be applied to (X<Y<Z>>,Y) method(new X<Y<Z>>(), rawObject); My types knowledge isn't up to knowing which is right. T is constrained as T super Y and X<T> super X<Y<Z>>. The only way I can see that these constraints could be satisfied is if erasure can have an effect far earlier than I thought, so that trivially T=Y. Surely we can't assume that the raw object will be a Y<Z> from the type parameter of X? Wildcarding the method signature will avoid the problem, though the issue remains for one of the compilers. public <T> void method(X<? extends T> x, T t) {}
My analysis, based on JLS 15.12.2.7, yields that 'T' is inferred to be 'Y<Z>', as we currently obtain with ECJ. ------------------------------------------------- 15.12.2.7 invoking: #method(X<T>,T) with { X<Y<Z>>, Y } i.e. Arg1 << Formal1, Arg2 << Formal2 (1) X<<Y<Z>> << X<T> (2) Y << T ------------------------------------------------- (1) X<<Y<Z>> << X<T> Using p.453: ❖ If F has the form G<..., Yk-1, U, Yk+1, ...>, where U is a type expression that involves Tj, then if A has a supertype of the form G<..., Xk-1, V, Xk+1, ...> where V is a type expression, this algorithm is applied recursively to the constraint V = U. [where U is T, V is Y<Z>] (1a) Y<Z> = T Using p.456: ❖ If F = Tj, then the constraint Tj = A is implied. (1b) T = Y<Z> ------------------------------------------------- (2) Y << T Using p.453: ❖ Otherwise, if F = Tj, then the constraint Tj :> A is implied. (2a) T :> Y ------------------------------------------------- p.463 resolving constraints: { T = Y<Z>, T :> Y } Using: "For each implied equality constraint Tj = U or U = Tj: • If U is not one of the type parameters of the method, then U is the type inferred for Tj. Then all remaining constraints involving Tj are rewritten such that Tj is replaced with U. There are necessarily no further equality constraints involving Tj, and processing continues with the next type parameter, if any." { T = Y<Z>, Y<Z> :> Y } Using: "Then, for each remaining type variable Tj, ..." There is none, hence the ':>' constraint is not considered; and T = Y<Z>. Applicability check does pass, with unchecked warning on second argument (raw Y).
I got confirmation from spec master that this is the intended behavior by the language spec. Please report the bug to javac.
marking as Invalid
Added GenericTypeTest#test1349
javac bug should soon be avail at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6718364
Verified for 3.5M1 using I20080805-1307