Wildcard capture with self-referencing bound

Dan Smith daniel.smith at oracle.com
Mon Jun 29 20:33:27 UTC 2015


See also:
https://bugs.openjdk.java.net/browse/JDK-8054937 <https://bugs.openjdk.java.net/browse/JDK-8054937>

—Dan

> On Jun 24, 2015, at 3:26 AM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
> 
> Hi,
> these are all areas where the JLS text is a bit underspecified and javac ended up settling on some opportunistic strategy which then, eventually, also got adopted by other compilers too. For instance, w.r.t. generic type well-formedness, the check performed by javac depends on the type-argument kind:
> 
> * if the type-argument T is invariant (i.e. not a wildcard type) - check that T <: B 
> * if the type argument T is a wildcard:
>     -of the kind ? extends A - check A _is castable_ to B
>     -of the kind ? super A - check that there exist some instantiation of A such that A <: B
>     -of the kind ? - always valid
> 
> I found a very similar explanation buried in the Java generic forums - and it seemed like, at the time (JSR14), Neal Gafter thought this     was a good compromise between safety and expressiveness. The spec ended up being written in a different - much stricter way, as you point out; as a result a lot of programs that are compiled w/o errors by javac are morally rejected by the spec. We might do some work in this area to align the compiler and the spec; note also that the compiler impl is too liberal/fuzzy, while the spec is too strict, so the 'optimal' result is probably somewhere in the middle.
> 
> Intersection types are also another deeply unspecified area; as you say, it is not clear what happens when the intersection components are wildcard types; we had few issues in javac related to this and we ended up forcing a capture conversion on the intersection type components. Again, this is probably not the behavior we'd like to have in the long run - think of it as an expedient to get things back on track.
> 
> Cheers
> Maurizio
> 
> On 12/06/15 00:40, Zhong Yu wrote:
>> Elias Vasylenko posted this question on http://stackoverflow.com/questions/30788366 <http://stackoverflow.com/questions/30788366>
>> 
>> Given declarations
>> 
>>     class C1<T extends C1<T>> {}
>>     class C2<U> extends C1<C2<U>> {}
>> 
>> Are the following parameterization well-formed?
>> 
>>     C1<? extends C2<String>>
>>     C1<? extends C2<?>>
>> 
>> According to his interpretation of JLS, which I concur, they are not well-formed, because the bound of the capture variable, T#1, is C2<String> & C1<T#1>, which is forbidden by both section $4.9 and $5.1.10.  Nothing in JLS will infer that C2<String> <: C1<T#1>.
>> 
>> However, javac does allow them, which is reasonable, of course. How do we understand this behavior?
>> 
>> Another question, if Ck in $4.9 contains wildcard like C2<?>, how can we use it as the superclass of the notional class? How do we derive members of the notional class?
>> 
>> Thanks,
>> Zhong Yu
>> bayou.io <http://bayou.io/>

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


More information about the compiler-dev mailing list