arrays and raw types in 18.2.3
Dan Smith
daniel.smith at oracle.com
Tue Oct 15 15:04:45 PDT 2013
On Oct 10, 2013, at 6:01 AM, Stephan Herrmann <stephan.herrmann at berlin.de> wrote:
>>> I'm currently looking at this test:
>>>
>>> public class X {
>>> public static void main(String[] args) {
>>> EntityKey entityKey = null;
>>> new EntityCondenser().condense(entityKey);
>>> }
>>> public static class EntityCondenser {
>>> <I, E extends EntityType<I, E, K>, K extends EntityKey<I>> void condense(K entityKey) {
>>> }
>>> }
>>> public class EntityKey<I> {}
>>> public interface EntityType<
>>> I,
>>> E extends EntityType<I, E, K>,
>>> K extends EntityKey<I>> {
>>> }
>>> }
>>
>> Ah, okay, in this case, there is no compatibility constraint for the two types ("Raw -> Parameterized"), just a subtyping constraint ("Raw <: Parameterized"), which is derived from the bound of K.
>>
>> The old spec was somewhat vague here, but I believe the correct behavior for both 7 and 8 is to fail.
>
> If that is so, then all(?) existing compilers have a bug: they do accept this program.
> I just checked, even javac8 b109 accepts the above test.
> Will this be changed in the near future?
It would not surprise me if there are some subtle changes between JLS 7 and JLS 8 lurking here, but I'm confident that JLS 7 calls this particular example an error.
I've confirmed that this is longstanding behavior in javac, and will report a bug.
---
Here's a simplified variation:
class EntityKey<T> {}
<I, K extends EntityKey<I>> void condense(K entityKey) {}
EntityKey entityKey = null;
condense(entityKey);
-----
Here's what JLS says:
15.12.2.2 tests applicability by subtyping.
U1 and U2 are the type arguments inferred for this invocation via initial constraint:
EntityKey << K
15.12.2.7 says:
- 'K' involves a type parameter
- 'EntityKey' is not the type of 'null'
- 'EntityKey' is not a primitive type
- 'K' is a type parameter, so the constraint 'K :> EntityKey' is implied
- Final constraints: 'K :> EntityKey'
- There are no equality constraints
- The type of K is inferred as lub(EntityKey) = EntityKey
So U1=??? (this is not well-defined) and U2=EntityKey.
Let S1 = K[I=???, K=EntityKey] = EntityKey
Is it the case that:
- A1 <: S1, that is, EntityKey <: EntityKey? Yes.
- U2 <: B2[I=???, K=EntityKey], that is, EntityKey <: EntityKey<???>? No.
So the method is not applicable. The rules go out of their way to allow an unchecked conversion, if necessary, in that first condition, but not the second.
The same reasoning applies for 15.12.2.3.
This flirts with the problem that we haven't clearly specified what U1 is supposed to be, but, really, it's irrelevant. If U2=EntityKey, no choice for U1 will allow U2 to be within its bound.
—Dan
More information about the lambda-spec-experts
mailing list