JDK-6863465 : javac doesn't detect circular subclass dependencies via qualified names
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6u13
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2009-07-23
  • Updated: 2023-11-17
  • Resolved: 2011-03-07
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.
JDK 7
7 b114Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) 64-Bit Server VM (build 11.3-b02, mixed mode)

javac 1.6.0_13

ADDITIONAL OS VERSION INFORMATION :
2.6.28-13-generic #45-Ubuntu SMP Tue Jun 30 22:12:12 UTC 2009 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
The example code below (four variations) describes a conceptually valid class hierarchy, but in each case 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 either as a superclass or superinterface, or AS A QUALIFIER of a superclass or superinterface name" ... "It is a compile-time error if a class depends on itself." -- emphasis mine.)  Javac will compile two of the examples without error, and reports misleading errors in the other two cases.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the following programs (cleaning up after any successful compiles to prevent javac from relying on previously-compiled class files):

*** Example 1

class a { static interface b {} }
class c extends a implements z.y {}

class x { static interface y {} }
class z extends x implements c.b {}

*** Example 2 (added another superinterface of c)

class a { static interface b { static interface d {} } }
class c extends a implements z.y, z.d {}

class x { static interface y {} }
class z extends x implements c.b {}

*** Example 3 (changed declaration order)

class x { static interface y {} }
class z extends x implements c.b {}

class a { static interface b { static interface d {} } }
class c extends a implements z.y, z.d {}

*** Example 4 (added another superinterface of z)

class a { static interface b { static interface d {} } }
class c extends a implements z.y, z.d {}

class x { static interface y { static interface w {} } }
class z extends x implements c.b, c.w {}


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
In each case, report a cyclical dependency in the declaration of the hierarchy.  (Eclipse does this successfully.)
ACTUAL -
*** Example 1: [javac reports no error.]

*** Example 2: [javac reports no error.]

*** Example 3:
circular.java:5: cannot find symbol
symbol  : class d
location: class z
class c extends a implements z.y, z.d {}
                                   ^
1 error

*** Example 4:
circular.java:6: cannot find symbol
symbol  : class w
location: class c
class z extends x implements c.b, c.w {}
                                   ^
1 error



REPRODUCIBILITY :
This bug can be reproduced always.

Comments
EVALUATION The problem is caused by the fact that the routine that implements the JLS check for cyclic inheritance is based on symbols - as a result, the compiler cannot tell as to whether a name is qualified or not. The solution is to consider trees in addition to symbols (note: symbols can't be completely dropped, as a class hierarchy might partially reside on classfile).
18-09-2010

SUGGESTED FIX A webrev of this fix is available at the following URL: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/0c1ef2af7a8e
18-09-2010