Wildcard capture with self-referencing bound
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Jun 24 09:26:06 UTC 2015
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
>
> 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