Summary: | [1.5][compiler] Eclipse compiler uses context of call to resolve type parameter, jdk1.5.0_06 does not. | ||||||
---|---|---|---|---|---|---|---|
Product: | [Eclipse Project] JDT | Reporter: | Wim Veldhuis <veldhuis> | ||||
Component: | Core | Assignee: | Philipe Mulet <philippe_mulet> | ||||
Status: | VERIFIED INVALID | QA Contact: | |||||
Severity: | normal | ||||||
Priority: | P3 | CC: | Olivier_Thomann | ||||
Version: | 3.3.1 | ||||||
Target Milestone: | 3.4 M6 | ||||||
Hardware: | PC | ||||||
OS: | Windows XP | ||||||
Whiteboard: | |||||||
Attachments: |
|
reproduced with HEAD When inferring generic method arguments, the compiler has to use contextual information from argument types, expected type etc... Inference performs in 2 steps: JLS 15.12.2.7 and JLS 15.12.2.8 (if previous did not solve the problem entirely). For clarity purpose, I renamed type param B into D (since name is confusing with member type B). Here it is (this doesn't change the behavior observed): import java.util.ArrayList; import java.util.List; public class TestUpCast { public static <D, E extends D> List<D> moreGeneric(List<E> list) { List<D> result = new ArrayList<D>(); result.addAll( list ); return result; } class A {} class B extends A {} public static void main( String[] args ) { List<B> b = new ArrayList<B>(); List<A> a = moreGeneric(b); } } Stage 1 - According to 15.12.2.7, inference is going to be fed with invocation arguments, i.e. inject the following constraints: List <B> << List<E> which yields E == B This leaves D unbound, hence need to involve more inference. Stage 2 - According to 15.12.2.8, inference now considers expected type and bounds of type variables, i.e. inject the following constraints: List<A> >> List<D> B << D which yields D == A So in the end, our behavior looks correct, and I would rather question javac's behavior. fyi - javac 1.7.0-ea-b24 agrees with us Closing as invalid. This is a javac bug. Added GenericTypeTest#test1292-1293 Erratum, tests are Added GenericTypeTest#test1291-1292 Verified for 3.4M6 using I20080324-1300. |
Created attachment 89534 [details] Sample code showing the problem. Build ID: M20070921-1145 Steps To Reproduce: 1. Compile code sample in eclipse, works 2. Compile using sun jdk1.5.0_06 compiler, fails 3. Error is: .\TestUpCast.java:19: incompatible types found : java.util.List<testcases.TestUpCast.B> required: java.util.List<testcases.TestUpCast.A> List<A> a = moreGeneric(b); ^ 1 error More information: Following class produces the error. package testcases; import java.util.ArrayList; import java.util.List; public class TestUpCast { public static <B, E extends B> List<B> moreGeneric(List<E> list) { List<B> result = new ArrayList<B>(); result.addAll( list ); return result; } class A {} class B extends A {} public static void main( String[] args ) { List<B> b = new ArrayList<B>(); List<A> a = moreGeneric(b); } } It seems like eclipse uses information from the calling context to resolve generic parameter B, where the sun jdk does not. Changing moreGeneric's signature to public static <B, E extends B> List<B> moreGeneric(Class<B> class, List<E> list) does work for sun as it then can figure out what B should be (the class is supplied in the call). I am not sure, but suspect eclipse supports some 1.6 features here. Settings for eclipse are to use the Java 1.5.0_06 JDK with Java 5.0 compliance (all other values default from the installed JDK). I would expect the eclipse compiler to behave the same as sun's.