Duplicate :
|
FULL PRODUCT VERSION : javac 1.6.0_20 java version "1.6.0_20" Java(TM) SE Runtime Environment (build 1.6.0_20-b02-279-10M3065) Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01-279, mixed mode) ADDITIONAL OS VERSION INFORMATION : Linux mini 2.6.32-gentoo-r7 #2 SMP Sat Jun 26 10:59:21 JST 2010 i686 Intel(R) Core(TM)2 Duo CPU E8235 @ 2.80GHz GenuineIntel GNU/Linux Windows XP SP3 (Sun JDK 1.6.0_20) Mac OS X 10.6.4 (Apple JDK 1.6.0_20) A DESCRIPTION OF THE PROBLEM : When compiling the attached source, compiler cannot infer the type variable T in the case map4: <T> Map<T, T> createMap() {return null;} ... Map<? super Integer, Integer> map4 = createMap(); However, compiler can infer the type variable in the case map1: Map<Integer, ? super Integer> map1 = createMap(); When I specify the type argument explicitly, comple success: Map<? super Integer, Integer> map2 = this.<Integer>createMap(); Moreover, replacing keyword 'super' with 'extends' also make compile success: Map<? extends Integer, Integer> map3 = createMap(); Accordding to the type inference algorithm specified in JLS 15.12.2.7 and 15.12.2.8, type inference must success as follows: 1. Since there is no arguments, no type variables are infered. 2. Since the return value is assigned to a variable, the type of the variable is taken into account. 2.1. The type S in JLS 15.12.2.8 is Map<? super Integer, Integer>, and R and R' is Map<T, T>. 2.2. The constraint Map<? super Integer, Integer> >> Map<T, T> is added to the constraint set. 3. Now, we will back to the type inference algorithm at 15.12.2.7. The constraint Map<? super Integer, Integer> >> Map<T, T> is decomposed to Integer << T and Integer = T. 4. The constraint Integer << T is converted to T :> Integer, and Integer = T is converted T = Integer. 5. Since equality constraints are resolved first, the constraint T = Integer is resolved with substitution T |-> Integer (in this bug report, U |-> V represents substitution of V for U). 6. The substitution T |-> Integer is applied to all remaining constraints, so that the constraint T :> Integer is now Integer :> Integer. 7. Since the relation :> is reflective (JLS 4.10), the constraint Integer :> Integer is satisfied. 8. Since all constraints are solved, the type inference algorithm ends successfully with a substitution T |-> Integer. Additional notes: The internal compiler of eclipse 3.5 can compile successfully. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Compile attached source: javac test.java EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - Compile without error. The type variable T is infered as a Integer. ACTUAL - Compiler cannot find instance of the type variable T, so that compile fails. ERROR MESSAGES/STACK TRACES THAT OCCUR : test.java:15: incompatible types; no instance(s) of type variable(s) T exist so that java.util.Map<T,T> conforms to java.util.Map<? super java.lang.Integer,java.lang.Integer> found : <T>java.util.Map<T,T> required: java.util.Map<? super java.lang.Integer,java.lang.Integer> Map<? super Integer, Integer> map4 = createMap(); ^ 1 error REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.util.*; public class test { public void foo() { // OK Map<Integer, ? super Integer> map1 = createMap(); // OK Map<? super Integer, Integer> map2 = this.<Integer>createMap(); // OK Map<? extends Integer, Integer> map3 = createMap(); // NG Map<? super Integer, Integer> map4 = createMap(); } public <T> Map<T, T> createMap() { return null; } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Specify the type arguments explicitly.