A bug in the Java 8 compiler.

Remi Forax forax at univ-mlv.fr
Wed May 25 10:55:52 UTC 2016



----- Mail original -----
> De: "Andrej Golovnin" <andrej.golovnin at gmail.com>
> À: "Compiler Dev" <compiler-dev at openjdk.java.net>
> Envoyé: Mercredi 25 Mai 2016 10:41:37
> Objet: A bug in the Java 8 compiler.
> 
> Hi all,
> 
> consider following code:
> 
> public class Main {
> 
>     public static class Details {
>         // NOP
>     }
> 
>     public static class Mapper<T> {
> 
>         public T getMapped(String str) {
>             return null;
>         }
> 
>         public List<Details> getDetails(T entity) {
>             return Collections.emptyList();
>         }
> 
>     }
> 
>     public static List<Details> calcDetails() {
>         Optional<Mapper> opt = Optional.empty();
>         return opt.map(m -> getDetails("A", m))
>                   .orElseGet(() -> Collections.emptyList());
>     }
> 
>     private static <E> List<Details> getDetails(String str,
>            Mapper<E> mapper)
>     {
>         E entity = mapper.getMapped(str);
>         return mapper.getDetails(entity);
>     }
> 
> }
> 
> 
> When I try to compile it, I get following error message:
> 
> Main.java:29: error: incompatible types: Object cannot be converted to
> List<Details>
>                   .orElseGet(() -> Collections.emptyList());
>                             ^
> Note: Main.java uses unchecked or unsafe operations.
> Note: Recompile with -Xlint:unchecked for details.
> 1 error
> 
> Neither Eclipse nor Intellij IDEA show an error in the line 29.
> The Eclipse Java Compiler is able to compile this code.
> And the latest JDK 9 compiler is able to compile this code too.
> But the problem is still reproducible in JDK 8u102 Build 04.
> It would be nice if you could fix it in JDK 8 too as we hit this problem
> multiple times in our project. And I'm sure other developers may hit
> this problem too.
> 
> Adding a cast fixes the problem for now:
> 
>     public static List<Details> calcDetails() {
>         Optional<Mapper> opt = Optional.empty();
>         return (List<Details>) opt.map(m -> getDetails("A", m))
>                   .orElseGet(() -> Collections.emptyList());
>     }
> 

Optional<Mapper> is a rare type i.e. a mix between a parameterized type and a raw type, declaring opt as a, Optional<Mapper<?>> instead should solve your issue.

FWIW, I'm no sure it's not a regression of jdk 9 instead of a bug in jdk8 (trying to do inference with a rare type).

> 
> Best regards,
> Andrej Golovnin
> 

Rémi


More information about the compiler-dev mailing list