Wildcard capture with self-referencing bound

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Jun 24 09:26:06 UTC 2015

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.


On 12/06/15 00:40, Zhong Yu wrote:
> Elias Vasylenko posted this question on 
> 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/20150624/341b5933/attachment.html>

More information about the compiler-dev mailing list