JDK-6971909 : A type inference with assignment conversion (JLS 15.12.2.8) fails
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6u10
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2010-07-23
  • Updated: 2012-03-20
  • Resolved: 2010-12-01
Related Reports
Duplicate :  
Description
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.