JDK-6391197 : static import seems to hide non-static import in a very special case
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0,6,7
  • Priority: P3
  • Status: Resolved
  • Resolution: Duplicate
  • OS: generic,linux,windows_xp
  • CPU: generic,x86
  • Submitted: 2006-02-27
  • Updated: 2013-05-30
  • Resolved: 2013-05-30
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 8
8Resolved
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-beta-b59g)
Java HotSpot(TM) Client VM (build 1.6.0-beta-b59g, mixed mode, sharing)

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

A DESCRIPTION OF THE PROBLEM :
The following piece of code produces with JDK 1.5.0_06 and JDK 1.6.0beta a compiler error.
####
package test;

import static test.Outer.Inner.CONST;
import java.util.Iterator;

class Outer {
  interface Inner extends Iterator {
    static String CONST = "CONST";
  }
}
####
The compilers produce the described error only in this special case. When putting the non-static import im front of the static import, the piece of code compiles fine. Example:
####
import java.util.Iterator;
import static test.Outer.Inner.CONST;
####
The symbol Iterator cannot be found only for the "extends Iterator" part. When omitting this part and using Iterator inside the inner interface, the piece of code also compiles fine. Example:
####
package test;

import static test.Outer.Inner.CONST;
import java.util.Iterator;

class Outer {
  interface Inner {
    static String CONST = "CONST";

    Iterator iterator();
  }
}
####
The bug cannot be produced in the outer class. When trying it, the pice of code also compiles fine. Example:
####
package test;

import static test.Outer.CONST;
import java.util.Iterator;

interface Outer extends Iterator {
  static String CONST = "CONST";
}
####
I.e., in the very special case of a static import of an inner class/interface's field followed by a non-static import of a class/interface, the inner class/interface extends/implements, the compiler produces an error. When changing one of this assumptions, the piece of code compiles fine.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Try to compile the following piece of code
####
package test;

import static test.Outer.Inner.CONST;
import java.util.Iterator;

class Outer {
  interface Inner extends Iterator {
    static String CONST = "CONST";
  }
}
####

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The compiler should compile the piece of code without any error (perhaps a warning that in inner interface Inner static import CONST and static field CONST are hiding each other).
ACTUAL -
The compiler produces the following compiler error
####
test\Outer.java:9: cannot find symbol
symbol  : class Iterator
location: class test.Outer
        interface Inner extends Iterator {
                                ^
1 error
####

ERROR MESSAGES/STACK TRACES THAT OCCUR :
test\Outer.java:9: cannot find symbol
symbol  : class Iterator
location: class test.Outer
        interface Inner extends Iterator {
                                ^
1 error


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package test;

import static test.Outer.Inner.CONST;
import java.util.Iterator;

class Outer {
  interface Inner extends Iterator {
    static String CONST = "CONST";
  }
}

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

CUSTOMER SUBMITTED WORKAROUND :
Simply put the non-static import in front of the static import.
Same problem reported by a CAP member:

J2SE Version (please include all output from java -version flag):
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)

Does this problem occur on J2SE 1.4.x or 5.0.x or 6.0?  Yes / No (pick one) 
Yes

Operating System Configuration Information (be specific):
Microsoft Windows XP [Version 5.1.2600]

Compiler not finding classes following static imports

Note: This might be a duplicate of Bug 6391197

When compiling the code the compiler reports:

test\Class1.java: cannot find symbol
symbol  : class JWindow
location: class test\Class1
  private static class Class1Window extends JWindow {

Workarounds:
1) switching the order of the import statements works (although they often get changed back by our development tools).
2) Commenting out the static import statements, then compiling, then putting the import statements back and compiling again with the old classes still there also works.
This means that the compiler errors happen at the strangest of times, and in large programs it can be very difficult to work out how to workaround the problems.

----------------- test.Class1.java -------------------------
package test;

import static test.Class2.*;
import javax.swing.*;

public class Class1 {
  private static class Class1Window extends JWindow { 
  }
}
----------------- test.Class2.java -------------------------
package test;

import static test.Class1.*;

public class Class2 {
}
--------------------------------------------------------------

Comments
EVALUATION This is a bad race in symbol completion: when the sourcefile is entered (MemberEnter) and the import statements are processed, the first import static statement makes the compiler jump to attribution of the Outer.Inner class (this is necessary, as the compiler must know the type of the field that is statically imported). Unfortunately, the declaration of Outer.Inner contains an extend clause that depends on a type, namely Iterator, whose import statement has not been processed yet. Hence the compiler error. Conceptually, the right order in which import statements should be evaluated is a lazy order: if ImportScope were computed lazily, so that ImportScope knows whther it has unevaluated import statements to be evaluated, then the lookup of Iterator would cause ImportScope to check through remaining unattred import decls before returning "not found". This means that import scopes should proviode a completion mechanism in order to lazily compute any pending unattributed import statement - such mechanism would likely be used in a transparent way by javac resolution classes. It is likely that, by fixing 6297388, this issue will go away.
22-11-2010

EVALUATION This is not just a problem for static imports as illustrated by the example from bug 6431987. Both examples share this part of the stack trace: at com.sun.tools.javac.code.Symbol.complete(Symbol.java:386) at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:758) at com.sun.tools.javac.code.Symbol$ClassSymbol.flags(Symbol.java:690) at com.sun.tools.javac.comp.Resolve.isAccessible(Resolve.java:181) at com.sun.tools.javac.comp.Resolve.findMemberType(Resolve.java:869) at com.sun.tools.javac.comp.Resolve.findIdentInType(Resolve.java:1039) at com.sun.tools.javac.comp.Attr.selectSym(Attr.java:1940) at com.sun.tools.javac.comp.Attr.visitSelect(Attr.java:1832) at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:1522) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360) at com.sun.tools.javac.comp.MemberEnter.visitImport(MemberEnter.java:527)
04-10-2006

EVALUATION This is a bug.
27-02-2006