Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8314380

JLS 4. 10. 4. Least Upper Bound is a complete gibberish (full of bugs)




      [Component = specification, Subcomponent = language]
      Here I list up all the mistakes, ill definitions, ambiguities, worth-improving points, and personal questions (sorry) that I have found in JLS 4. 10. 4:

      (0) JDK-8071963
      (1) The following line is 'simply total crap', as somebody mentioned in stackoverflow:
                lcta(U) = ? if U's upper bound is Object, otherwise ? extends lub(U,Object)
           First, U is a general type. no concept like 'upper bound' is defined about it. Even if U is a type variable,
           Why not <U> instead of meaninglessly wider and laughably redundant <? extends lub(U, Object)>.
      (2) The lcp is ill-defined. The jls says the lcp for a set of types is defined by consecutive pairwise applications
           of the listed rules to a list of its elements. This works as a definition only when (a) the set is finite and
           (b) the result does not depend of the order of the sequence. But (b) is not true.
           Think of the lcp of the set {Set<Component>, Set<Window>, Set<? super Frame>}.
           If the list the set is transformed into is [Set<Component>, Set<Window>, Set<? super Frame>],
           then lcp is Set<?>; elif [Set<? super Frame>, Set<Component>, Set<Window>],
           Set<? super Frame>. Now you can see the lcp is not well-defined for this type set.
      (3) In my example above, I implicitly transformed Window & Frame to Frame, but I think there is, technically,
           nothing that justifies that transformation in JLS. Was I right doing that? (Sorry not related to 4_10_4.)
      (4) In the example shown in the jls, it says "ST(List<String>) = { List<String>, Collection<String>, Object }".
           Not true. The set of all the subtypes contains List. It goes on saying "lost track of the fact that the
           upper bound can safely be assumed to be a List." Not true. Yes we all know the importance of EST,
           so you may think I am just too meany. Not true. Considering what ST really is will reveal
           other problems of 4_10_4 that essentially make this definition of lub a complete gibberish.
      (5) ST(ArrayList<Object>) contains List<? super Integer>, List<? super System>, List<? super Thread>, ...
           Then, what is Relevant(List)? Relevant is defined in the following formula:
                { V | 1 ≤ i ≤ k: V in ST(Ui) and V = G<...> }.
           Let us make it clear. This states "all the type V's such that there exists i such that V is in ST(Ui) and that
           V is a parametrization", right? Oh, no! All the List<? super ...>s are in Relevant(G)?
           So, next, lcp is applied to this infinite set, which is against (a) which I have stated in (2).
           And even if I favorably allows lcp to be applied to an infinite set, it generates <?> out of
           finite<? extends ...> and infinite <? super ...>, all of which come just from one ArrayList<Object>.
           No matter what Lists the args of lub may have, <?> inevitably.
           Okay I've been really mean here. What we need would be fixing the definition of Relevant
           to make it somehow choose the most lower parametrizations for each i.
      (6) Wait, what is ST(ArrayList<? extends Runnable>)? List<...> is not the direct super of it. We must
           perform a capture conversion first, ArrayList<CAPTURE>. Then List<CAPTURE>.
           The other elements of ST in the form List<...> will be obtained by replacing CAPTURE with
           a wildcard that contains the CAPTURE. If I don't allow Relevant to choose the most lower parametrization,
           unlike I have proposed in (5), infinite <? super ...>s. Finally, <?>. If make it choose, List<CAPTURE>.
           I think it is in another way problematic. Most lub calculations will end up using the lcta rule for two
          different types:
                lcta(T, U) = <? extends lub(T, U)>
          with T and U being captures of one thing and of another. The other fascinating rules, especially
          those mentioning '? super ...', will lose almost all their opportunities to be used. And the resulting lub will be
          full of captures. Should I convert such captures back to wildcards before applying lcta rules?
          What about the case like where, for example,
                class Base<X, Y, Z> {}
                class Soup<T> extends <T[], List<? super T>, Map<? extends T[], T> {}
          and thinking of lub(Soup<? extends Something>,...) and MEC contains Base?
          Now the capture will be deep in the Base's parametrization. Do we leave them this time?
          Actually, though I have written long, this is the main point for which I want an answer and a fix.
      (7) If a generic class Generic<X>'s raw type Generic is in MEC, but any of the args of lub U_1, U_2, ... extends
           just the raw type Generic, not its parametrization, then a type that will appear in the lub is
           Best(Generic) = Candidate(Generic) = lcp(Relevant(Generic)) = lcp(empty set) --- What is this?
           When saying Relevant(Generic) is empty, I interpreted the condition 'V = G<...>' as V is a parametrization
           of G. No parametrizations of Generic in ST(U_i) for any i. If this condition, against how it looks,
           is ever allowing V to be the raw type of G, this time, lcp must be defined for the cases a raw type is involved.
      (8) A bit curious about whether the unmentioned equating mechanism about which I asked in another report
           (internal review ID : 9064421) is active during this process or not, especially when judging T == U.

      FREQUENCY : always


        Issue Links



              Unassigned Unassigned
              webbuggrp Webbug Group
              0 Vote for this issue
              3 Start watching this issue