JDK-8078095 : 4.10.4: Fix dependency on unspecified "infinite types" in lub
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2015-04-17
  • Updated: 2019-02-22
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbd_majorUnresolved
Related Reports
Blocks :  
Description
A useful feature of lub (JLS 4.10.4) is its ability to handle multiple parameterizations of the same generic class by introducing a wildcard that encompasses both parameterizations.

    lub(List<S>, List<T>) = List<? extends lub(S,T)>

Unfortunately, in general this recursion does not terminate.  For example:

    interface A extends Comparable<A> {}
    interface B extends Comparable<B> {}

    lub(A,B) = Comparable<? extends Comparable<? extends Comparable<...>>>

This problem is acknowledged by JLS, with the unhelpful note that "a compiler for the Java programming language must recognize such situations and represent them appropriately using cyclic data structures".  This note fails to recognize that simply _encoding_ these types is not sufficient for accurately _reasoning_ about them.

One solution could be to explore the theoretical implications of these types and fully specify them.  They seem similar to equi-recursive types, although JLS claims they are different.  To scratch the surface, we would need a definition of subtyping that is able to handle a test like

        Iterable<? extends List<? extends Iterable<...>>> <: Iterable<? extends Iterable<...>>

However, acknowledging that it is rare for the precision of this infinite wildcard bound to be of practical use, we could simply define the _lub_ to produce a slightly weaker bound after one or two loops:

        lub(A,B) = Comparable<? extends Comparable<?>>

This is the strategy javac has been silently using since Java 5 (with an outstanding bug to come back and "fix" it: see JDK-4993221).
Comments
A solution here should also clarify what is meant by the assertion that "an infinite type is not the same as a recursive type" (or delete it). The term "recursive type" can mean a lot of different things.
22-02-2019