Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6971909

A type inference with assignment conversion (JLS 15.12.2.8) fails

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 6u10
    • tools
    • x86
    • linux

      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.

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: