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

inference: lub of typevariables does not yield expected results

    • Icon: Enhancement Enhancement
    • Resolution: Unresolved
    • Icon: P4 P4
    • None
    • 5.0, 6
    • specification
    • Fix Understood
    • generic
    • generic

      Consider the example in 5042462.

      We have the following type variables:

      <T, U extends T, V extends T>

      The JLS (p463) defines lub in terms of the EST (erased supertype set).

      EST(U) = {Object} and
      EST(V) = {Object}.

      Then EC = { Object } = MEC.

      So lub(U,V) = Object.

      It should be T.

          [JDK-6488666] inference: lub of typevariables does not yield expected results

          Alex Buckley added a comment -
          BT2:EVALUATION

          I am inclined to think we should pass the bounds of every type argument to the inference process and use them in the lub calculation.

          Consider the example in 6557661, slightly modified below:

            <T> Map<T,T> foo(T t1, T t2) { return null; }

            <U extends Object, V extends U> Map<U,U> bar(U u, V v) {
              Map<Object,Object> map1 = foo(u, v); // Allowed by javac 1.6
              Map<U,U> map2 = foo(u, v); // Should be allowed
              return map2;
            }

          Suppose bar is called with U and V as some subtypes of a common supertype that isn't Object:
            Map<...,...> x = bar(new Sub1(), new Sub2());
          U is inferred as Sub1 and V as Sub2. For bar's own call to foo, a good lub would calculate T=lub(U,V)=U (=Sub1), so foo will return Map<U,U> (=Map<Sub1,Sub1>) which is safe to assign to map2 and return to the call ofer bar, which can safely expect a Map<Sub1,Sub1>.

          Alex Buckley added a comment - BT2:EVALUATION I am inclined to think we should pass the bounds of every type argument to the inference process and use them in the lub calculation. Consider the example in 6557661, slightly modified below:   <T> Map<T,T> foo(T t1, T t2) { return null; }   <U extends Object, V extends U> Map<U,U> bar(U u, V v) {     Map<Object,Object> map1 = foo(u, v); // Allowed by javac 1.6     Map<U,U> map2 = foo(u, v); // Should be allowed     return map2;   } Suppose bar is called with U and V as some subtypes of a common supertype that isn't Object:   Map<...,...> x = bar(new Sub1(), new Sub2()); U is inferred as Sub1 and V as Sub2. For bar's own call to foo, a good lub would calculate T=lub(U,V)=U (=Sub1), so foo will return Map<U,U> (=Map<Sub1,Sub1>) which is safe to assign to map2 and return to the call ofer bar, which can safely expect a Map<Sub1,Sub1>.

          Alex Buckley added a comment -
          BT2:EVALUATION

          It is ironic that the result is Object, since the Discussion on page 463 for using *erased* supertypes is precisely to avoid ending up with a lub of Object.

          Alex Buckley added a comment - BT2:EVALUATION It is ironic that the result is Object, since the Discussion on page 463 for using *erased* supertypes is precisely to avoid ending up with a lub of Object.

            abuckley Alex Buckley
            ahe Peter Ahe
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: