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

Unclear specification: circular class hierarchy dependency via static imports

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • None
    • 6u13
    • specification
    • Fix Understood
    • x86
    • linux_ubuntu

      FULL PRODUCT VERSION :


      A DESCRIPTION OF THE PROBLEM :
      A set of class declarations like the following, while modeling a reasonable, non-circular class hierarchy, is prohibited by the JLS (8.1.4 & 9.1.3, "A class C directly depends on a type T if T is mentioned in the extends or implements clause of C ... as a qualifier of a superclass" ... "It is a compile-time error if a class depends on itself."):

      ***
      class a { static interface b {} }
      class c extends a implements z.y {}
      class x { static interface y {} }
      class z extends x implements c.b {}
      // c directly depends on z, which directly depends on c
      ***

      I assume this restriction is in place to help simplify the task of a compiler, which would have to, for example, determine the meaning of the name "z.y" without having fully resolved the supertypes of class z. In general, in fact, this task would require fixed point logic to simultaneously determine the members of all classes involved in such a cycle. Expanding the above example a bit:

      ***
      class a { static interface b { static interface d { int i; } } }
      class c extends a implements z.y, z.d {}
      class x { static interface y { static interface w { int j; } } }
      class z extends x implements c.b, c.w {}
      // fixed point calculation of membership (a set of classes mapped to their members):
      // membership0 = { a:{}, b:{}, c:{}, d:{} x:{}, y:{}, z:{}, w:{} }
      // membership1 = { a:{ b }, b:{ d }, c:{}, d:{ i } x:{ y }, y:{ w }, z:{}, w:{ j } }
      // membership2 = { a:{ b }, b:{ d }, c:{ b }, d:{ i }, x:{ y }, y:{ w }, z:{ y }, w:{ j } }
      // membership3 = { a:{ b }, b:{ d }, c:{ b, w }, d:{ i }, x:{ y }, y:{ w }, z:{ y, d }, w:{ j } }
      // membership4 = { a:{ b }, b:{ d }, c:{ b, w, i }, d:{ i }, x:{ y }, y:{ w }, z:{ y, d, j }, w:{ j } }
      ***

      So it's reasonable to prohibit such class hierarchies.

      Unfortunately, static imports, because they allow member classes to be imported without referring to a canonical name, provide a workaround to defining the same class hierarchy:

      *** a.java
      package circular;
      class a { static interface b { static interface d {} } }
      *** c.java
      package circular;
      import static circular.z.y;
      import static circular.z.d;
      class c extends a implements y, d {}
      *** x.java
      package circular;
      class x { static interface y { static interface w {} } }
      *** z.java
      package circular;
      import static circular.c.b;
      import static circular.c.w;
      class z extends x implements b, w {}
      *****

      The specific language of the JLS does not apply here, because, for example, class z is not specifically mentioned in the extends/implements clauses of c. Yet the same complexity problems are present. It seems the intent of the JLS is to define "directly depends" in terms of static imports as well, but this is not made explicit.

      Current implementations (javac 1.6.0_13, Eclipse 20090619-0625) are unable to compile this last example (using static imports), but fail to identify the error as a circular dependency. javac 1.6.0_13 also fails to compile the first example when rewritten using static imports.


      REPRODUCIBILITY :
      This bug can be reproduced always.

            abuckley Alex Buckley
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: