Community
Participate
Working Groups
Build Identifier: 20110615-0604 Eclipse highlights code as a java error, but the java compiler does not. See the Steps to Reproduce for an example. Reproducible: Always Steps to Reproduce: 1. Create a class called 'GenericsTest' and paste the following within the class: public interface A<X> { X get(); void doStuff(X x); } public class Test { public <T extends A<?>> void foo(T t) { bar(t); } private <X> void bar(A<X> t) { X x = t.get(); t.doStuff(x); } } 2. Observe the error: The method bar(GenericsTest.A<X>) in the type GenericsTest.Test is not applicable for the arguments (T) 3. Compile outside of eclipse with javac. 4. Observe no errors.
This compiles fine with javac 1.6, but fails to compile with javac 1.7: Test.java:8: error: method bar in class Test cannot be applied to given types; bar(t); ^ required: A<X> found: T reason: actual argument T cannot be converted to A<CAP#1> by method invocation conversion where X,T are type-variables: X extends Object declared in method <X>bar(A<X>) T extends A<?> declared in method <T>foo(T) where CAP#1 is a fresh type-variable: CAP#1 extends Object from capture of ? 1 error
@Oliver Thompson, thank you for letting me know (as I didn't). I was using 1.6.0_27 as the JDK, so Eclipse is still identifying an error that the selected JDK is not. With respect to Java 7, this might be an error with that javac because bar( ( A<?> )t ); works and is arguably redundant since t is a T and T extends A<?> or am I misunderstanding something. Thank you for your help!
I believe the eclipse compiler behavior is correct and is matched by JDK5 and JDK7 (latest). It would appear the JDK6 behavior is a regression which has since been fixed. Basically, here is a brief explanation of what is going on here: Given the generic method bar and the call site as given by bar(t), the inference algorithm has no constrains to work with to infer the type of the type variable X. So after considering the arguments and expected return type etc, X is still unresolved and per specification is resolved to be the published lower bound - i.e X is inferred to be Object and the method becomes void bar(A<Object>) t); Since the actual parameters cannot be converted to formal parameters, the inferred method has to be rejected leaving us with no applicable candidates. Hence the call must be rejected. The reason the call bar( ( A<?> )t ); succeeds is that in this case X is inferred to be "capture#1-of ?" and the generic method parameterized with this substitution becomes void bar(A<capture#1-of ?>) for which the parameter compatibility holds. Closing as INVALID.
Verified for 3.8M5