Java 8 compiler bug?

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Nov 17 18:16:02 UTC 2016



On 17/11/16 17:19, Remi Forax wrote:
> I think the main issue is that when the inference fails, the compiler 
> instead of reporting an error continue using Object instead.
>
Where is inference failing in JDK 8? I think the 'problem' here is that 
the code below:

import java.util.*;

class Test {

     void test() {
         Expression<Object> objectExpression = null;
         Expression<Collection<Object>> collectionOfObjectExpression = null;
         m(objectExpression, collectionOfObjectExpression);
     }

     interface Expression<T> {}

     <E, C extends Collection<E>> void m(E elem, Expression<C> 
collection) { }
}


succeeds with -source N where N >= 8 and fails otherwise - which is a 
consequence of Java 8 inference being more powerful. In the original 
example, the fact that there was an overload, combined with the fact 
that inference used to fail for one of the overloaded methods meant that 
the program passed in source N < 8 but fails with ambiguity after 8 
because now overload resolution can consider both methods as being 
applicable.

Maurizio
> Remi
>
>
> On November 17, 2016 5:12:19 PM GMT+01:00, Maurizio Cimadamore 
> <maurizio.cimadamore at oracle.com> wrote:
>
>
>     On 17/11/16 13:56, Oliver Gierke wrote:
>
>         Hi Maurizio, answer inline…
>
>             Am 17.11.2016 um 13:44 schrieb Maurizio Cimadamore
>             <maurizio.cimadamore at oracle.com>: On 15/11/16 23:46,
>             Oliver Gierke wrote:
>
>                 CriteriaBuilder and all other types come from JPA. The
>                 method in question has two overloads: <E, C extends
>                 Collection<E>> Predicate isNotMember(Expression<E>
>                 elem, Expression<C> collection); <E, C extends
>                 Collection<E>> Predicate isNotMember(E elem,
>                 Expression<C> collection); I fai! l to understand why
>                 the second method is even considered as that create a
>                 contradiction between the bound values of E
>                 (Expression<…>) and C (Collection<Object>). 
>
>             Hi Oliver, I believe the JDK 8 behavior is correct here -
>             let's just consider your second method - which is the one
>             you have doubts about: <E, C extends Collection<E>>
>             Predicate isNotMember(E elem, Expression<C> collection);
>             Now, you want to pass the following actual argument types
>             to this method: arg1 = Expression<Object> arg2 =
>             Expression<Collection<Object>> So, let's look at which
>             constraints these argument cause trigger on our inference
>             variables E and C. So, since Expression<Object> must be
>             compatible with E - we have that Expression<Object> <: E
>             Then, since also Expression<Collection<Object>> must be
>             compatible with Expression<C> we have that:
>             Expression<Collection<Object>> <: C 
>
>         Is that correct? If the method parameter takes an
>         Expression<C> and we hand in an
>         Expression<Collection<Object>>, C should be bound to
>         Collection<Object>, not Expression<Collection<Object>>, right?
>         This basically where my confusion comes from, as that would
>         then render E to evaluate to Object for the second parameter
>         which then contradicts the E derived for the first one, right?
>         Cheers, Ollie
>
>
>     Let me reboot, as I made a bit of a mess :-)
>
>     You have:
>
>     Expression<Object> <: E
>
>
>     and
>
>     Expression<Collection<Object>> <: Expression<C>
>
>
>
>     The latter constraint produces:
>
>     C = Collection<Object>
>
>     And then you also have:
>
>     C <: Collection<E>
>
>     Th!
>       en from
>     transitivity you get
>
>     Collection<Object> <: Collection<E>
>
>     --> E = Object.
>
>     Note that this answer is correct - as we needed a type for E that was
>     _bigger_ than Expression<Object>, and Object is obviously one such type
>     (being Object the biggest possible type).
>
>     So, while I made a mistake in my derivation, the conclusion is still
>     valid: the treatment of transitivity (new in Java 8) allows this
>     inference to succeed, while the lack of it caused inference to fail in
>     Java 5, 6,7.
>
>     Maurizio
>
>
> -- 
> Sent from my Android device with K-9 Mail. Please excuse my brevity. 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20161117/049e47eb/attachment.html>


More information about the compiler-dev mailing list