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

javac inference allows creation of strange types: Integer & Runnable

XMLWordPrintable

    • b48
    • generic, x86
    • generic, linux
    • Verified

      This program should not compile:

      class Test<X extends Integer & Runnable> {
          private X x = null;
          public X getX() { return x; }
          public static <T extends Integer & Runnable> Test<T> factory() { return new Test<T>(); }
          public String toString() { return "Test("+x+")"; }
          public static void main(String[] args) {
              Test<?> t = Test.factory();
              Integer i = t.getX();
              Runnable r = t.getX();
              System.out.println("Peter won't be happy: "+t);
          }
      }

      The call to Test.factory should infer Object for T
      and thus fail. Object is not a subtype of Integer nor
      Runnable.
      However I discovered that javac is really sensitive to little differences in the source code; consider the following source:

      class Test<V> {
      <T extends Integer & Runnable> Test<T> m() {
              return null;
          }
          void test() {
              Test<?> c1 = m(); //1 - should compile
              Test<? extends String> c2 = m(); //2 - shouldn't compile
              Test<? super String> c3 = m(); //3 - shoudln't compile
          }
      }

      Surprisingly, javac rejects (1), which is wrong and, worse, diagnostics for both (2) and (3) reveal that something weird is going on:

      Test3.java:6: incompatible types; inferred type argument(s) java.lang.Object do not conform to bounds of type variable(s) T
      found : <T>Test<T>
      required: Test<?>
              Test<?> c1 = m();
                            ^
      Test3.java:7: incompatible types; inferred type argument(s) java.lang.String do not conform to bounds of type variable(s) T
      found : <T>Test<T>
      required: Test<? extends java.lang.String>
              Test<? extends String> c2 = m(); //2 - shoudln't compile
                                           ^
      Test3.java:8: incompatible types; inferred type argument(s) java.lang.Object do not conform to bounds of type variable(s) T
      found : <T>Test<T>
      required: Test<? super java.lang.String>
              Test<? super String> c3 = m(); //3 - shoudln't compile
                                         ^
      3 errors

      The inferred types are all wrong:

      (1) Object instead of Integer&Runnable
      (2) String instead of error (glb(String,Integer,Runnable)
      (3) Object instead of Integer&Runnable

            mcimadamore Maurizio Cimadamore
            ahe Peter Ahe
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: