Possible regression involving inferred generic types

Vicente-Arturo Romero-Zaldivar vicente.romero at oracle.com
Mon Nov 4 07:10:09 PST 2013


Hi Liam,

I have been investigating the issue you reported. The fix that changed 
javac's behavior is deep in current javac 8 repo, see [1], the original 
bug entry can be seen at [2].

 From my understanding of the spec and also based on Alex's answer at 
[3], I think that the fact that the code compiles in 7 is a bug and thus 
8 can be considered correct. For this reason I don't think that there is 
a compatibility issue here.

I have modified the code of ReproOne.java to:

--------------------------------------------------------------------------------
import java.util.List;

class ReproOne {

   static class Baz<T> {
     public static List<Baz<Object>> getElements(Baz<Object> transcoder) {
       return null;
     }
   }

   private static void bar(Baz arg) {
     Baz element = Baz.getElements(arg).get(0);
   }
}
-----------------------------------------------------------------------------------

Which probably shows more clearly the fact that after erasing the return 
value of getElements() to "java.util.List" the type of get(0) is Object 
and thus not assignable to a variable of type Baz.

Thanks,
Vicente.

[1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/48ee63caaa93
[2] https://bugs.openjdk.java.net/browse/JDK-7144506
[3] 
http://mail.openjdk.java.net/pipermail/compiler-dev/2013-October/007726.html

On 17/10/13 01:48, cushon wrote:
> Forwarded from compiler-dev at Alex Buckley's suggestion. Original thread:
> http://mail.openjdk.java.net/pipermail/compiler-dev/2013-October/007726.html
>
>
> I found some cases where javac 8 behaviour diverges from javac 7, and I'm
> interested in knowing whether this is a bug or an intentional change.
>
> The following programs do not compile with the jdk8 javac. (I tried b111 and
> 954dd199d6ff). All of the programs compile with the jdk7 javac.
>
> -------------------------------------------------------------------------------
> import java.util.List;
>
> class ReproOne {
>
>    static class Baz<T> {
>      public static List<Baz<Object>> getElements(Baz<Object> transcoder) {
>        return null;
>      }
>    }
>
>    private static void bar(Baz arg) {
>      for (Baz element : Baz.getElements(arg)) {}
>    }
> }
> -------------------------------------------------------------------------------
> abstract class ReproTwo<T> {
>
>    class Bar<E> {}
>
>    T get(Bar<? extends T> arg1, Bar arg2) {
>      return circularGet(arg2, arg2);
>    }
>
>    abstract T circularGet(final Bar<? extends T> arg1, final Bar<?> arg2);
> }
> -------------------------------------------------------------------------------
> abstract class ReproThree<T, V> {
>
>    class Binding<E> {}
>    class ProviderBinding<E> extends Binding<E> {}
>
>    abstract V visitOther(Binding<? extends T> binding);
>
>    public V visitTwo(ProviderBinding<? extends T> providerBinding) {
>      return visitOther((Binding) providerBinding);
>    }
> }
> -------------------------------------------------------------------------------
>
> javac output:
>
> ReproOne.java:12: error: incompatible types: Object cannot be converted to
> Baz
>      for (Baz element : Baz.getElements(arg)) {}
>                                        ^
>
> ReproTwo.java:6: error: incompatible types: Object cannot be converted to T
>      return circularGet(arg2, arg2);
>                        ^
>    where T is a type-variable:
>      T extends Object declared in class ReproTwo
>
> ReproThree.java:10: error: incompatible types: Object cannot be converted
> to V
>      return visitOther((Binding) providerBinding);
>                       ^
>    where V is a type-variable:
>      V extends Object declared in class ReproThree
>



More information about the lambda-dev mailing list