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

javac order of compilation incorrect when enums with interfaces are referenced

    Details

    • Subcomponent:
    • Understanding:
      Cause Known
    • Introduced In Version:
      5.0
    • CPU:
      x86
    • OS:
      windows_xp

      Description

      FULL PRODUCT VERSION :
      java version "1.6.0"
      Java(TM) SE Runtime Environment (build 1.6.0-b105)
      Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      Given an interface (I) with a method (m), and an enum (E, with constant X) that implements that interface (and thus X provides an implementation for M).
      Given another class that references the enum (C).
      Given that none of the corresponding class files exist.

      1) If C references m on X, javac will not recognize that E needs to be compiled, and will report a "symbol not found" error for the use of m.
      2) If C references m on X, but does so after casting X to I, javac will compile E.
      3) If C references one of the enum provided methods (such as toString) on X, javac will compile E.
      4) If m is also defined as a method on E, either abstract or not, javac will compile E. (This behaviour is regardless of X implementing m or not implementing m.)


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      public interface I {
       public String M();
      }

      public enum E implements I {
       Bob { public String m() { return "bob"; } };
      }

      public class C {
       public static void main(final String[] args) {
        System.out.println(E.Bob.m());
       }
      }

      When no class files exist, javac on C produces a "symbol not found" error for m on Bob.

      In the following two cases, javac performs as expected:
      public class C2 {
       public static void main(final String[] args) {
        System.out.println(E.Bob.toString());
       }
      }

      public class C3 {
       public static void main(final String[] args) {
        I iBob= E.Bob;
        System.out.println(iBob.m());
       }
      }


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected javac to detect that E needed to be compiled when C was being compiled.
      See Description and Steps to Reproduce.
      ACTUAL -
      javac gave a "symbol not found" error.
      See Description and Steps to Reproduce.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      in file I.java:
      public interface I {
       public String M();
      }

      in file E.java
      public enum E implements I {
       Bob { public String m() { return "bob"; } };
      }

      in file C.java
      public class C {
       public static void main(final String[] args) {
        System.out.println(E.Bob.m());
       }
      }

      javac C.java. Unknown symbol error on "Bob.m()" will be produced.

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      1) Specifically compile E before C;
      2) Cast E.Bob to I before invoking m. (see C3 in Steps to Reproduce)
      3) Put a duplicate definition of m into E, such that:
      public enum E implements I {
       Bob { public String m() { return "bob"; } };
       public abstract String m();
      }

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              ndcosta Nelson Dcosta
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Imported:
                Indexed: