Java 8 compiler bug?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Nov 17 16:12:19 UTC 2016
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 fail 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>
Then 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
More information about the compiler-dev
mailing list