JDK-6975015 : 7.5: Stricter prohibition against import from unnamed package
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 6,7,8
  • Priority: P5
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2010-08-05
  • Updated: 2018-08-03
  • Resolved: 2016-09-27
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 9
9Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8) (6b18-1.8-1)
OpenJDK Server VM (build 14.0-b16, mixed mode)

java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Server VM (build 16.3-b01, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux thirtyseven 2.6.32-5-686-bigmem #1 SMP Tue Jun 1 05:38:08 UTC 2010 i686 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
Subtypes of types contained in the default package cannot be imported using single-type import statements.  According to the JLS v3, single-type imports are to be provided with the canonical name of a class or interface type.  The canonical name of a top-level type is the fully-qualified name of that type.  The fully-qualified name of a top-level type declaration in the default package is the simple name of that type.  Therefore, a class named "Test" in the default package should be imported using the import statement "import Test;".

The compiler seems to assume, however, that a single-type import requires a qualified name.  This does not appear to be correct according to the JLS v3.  Specifically, the example grammar in S18.1 shows, on page 592, a definition of ImportDeclaration which allows imports of simple names.

This bug was discovered while I was confirming my understanding of the syntax of import statements for the purposes of writing a Java parser.  Our project will use the JLS-compliant syntax for the time being; it appears to be a superset of that currently allowed by the Java compiler which is, in this case, acceptable.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a new source directory (henceforth termed $src).  Create a directory $src/example.  Create a file $src/Test.java with the following content:

    public class Test { }

Create a file $src/example/Main.java with the following content:

    package example;
    import Test;
    public class Main {
        Test t;
    }

Compile both source files.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Binary output should be successfully generated.  The output example/Main.class should contain a reference to the class defined by Test.class.
ACTUAL -
The compiler fails to compile, indicating that package Test does not exist.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
example/Main.java:2: '.' expected
import Test;
           ^
example/Main.java:2: ';' expected
import Test;
            ^
2 errors


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Contents of Test.java:

    public class Test { }

Contents of example/Main.java:

    package example;
    import Test;
    public class Main {
        Test t;
    }

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

CUSTOMER SUBMITTED WORKAROUND :
No workaround exists short of moving the default package class to another package.

Comments
JLS7 7.5 added a note that "A type in an unnamed package has no canonical name, so the requirement for a canonical name in every kind of import declaration implies that ..." which assumed that canonical names would be redefined to exclude types in unnamed packages. For compatibility reasons, canonical names were _not_ redefined, and nor were fully qualified names, so JLS7 erroneously allowed imports of types in unnamed packages. In determining the path for JLS8, we encounter a longstanding and subtle question of declarations v. names. "import" statements are declarations (6.1), so SingleTypeImportDeclaration et al should use the Identifier nonterminal to introduce entities (types and members) which may then be referred to by name throughout the compilation unit. But since the entities are already declared elsewhere, we want the usual rules for interpreting a type name or package name to apply to the operand of an "import" statement. Indeed, 6.5.1 has always mandated the interpretation explicitly. To hint that the interpretation is necessary, 7.5 has always used TypeName and PackageOrTypeName instead of Identifier in SingleTypeImportDeclaration et al. Then, the interpretation rules in 6.5.4 and 6.5.5 require that a name given as the operand of an "import" statement actually exists as a type or package, so there is no need for 7.5.1 to mandate existence (as JLS3 did). But unfortunately, 6.5.4 and 6.5.5 allow a simple name of a type, which is undesirable in an "import" statement. Here is a formulation to restrict "import" statements to named packages: - 7.5.1: "The TypeName must be the canonical name of a class type, interface type, enum type, or annotation type. ***The type must be either a member of a named package, or a member of a type whose outermost lexically enclosing type is a member of a named package, or a compile-time error occurs.***" - 7.5.2: "The PackageOrTypeName must be the canonical name of either a package or a class type, interface type, enum type, or annotation type. ***If the PackageOrTypeName denotes a type (6.5.4), then the type must be either a member of a named package or a member of a type whose outermost lexically enclosing type is a member of a named package, or a compile-time error occurs.***" A simpler formulation relies on syntax, like javac does, and is preferred for JLS8: - 7.5.1: "... ***The name must be qualified, or a compile-time error occurs.***" - 7.5.2: "... ***If the PackageOrTypeName denotes a type (6.5.4), then the name must be qualified, or a compile-time error occurs.***" Finally: - 7.5.3 and 7.5.4 both copy 7.5.1. - 6.1 should also identify imported static members: "A declared entity is one of the following: ... An imported static member, declared in a single-static-import declaration or a static-import-on-demand declaration."
23-09-2015

The syntactic formulation allows import of a type nested in a top level type of an unnamed package, e.g., import static TopLevelCls.NestedCls.Member;. However, this has always been disallowed by javac and JCK-compiler. For JLS9, it is preferable to adopt the semantic formulation that's specific about named packages. (See private email thread: "JLS 8 vs 7: static import and unnamed package")
18-05-2015

While JLS3 does not syntactically prohibit "import Test", section 7.5 mandates a compiler error: - "A single-type-import declaration (��7.5.1) imports a single named type, by mentioning its canonical name (��6.7). - "A type-import-on-demand declaration (��7.5.2) imports all the accessible (��6.6) types of a named type or package as needed. It is a compile time error to import a type from the unnamed package." This phrasing is unclear and should be improved: because it's in a different paragraph, it's not clear that "It is a compile time error ..." applies to both single-type-imports and type-import-on-demands. But this is the intent. The fact that javac treats this as a syntax error is fine -- the implementation is free to enforce prescribed errors in whatever way is convenient. One reason for the prohibition is that implementations are allowed to have more than one unnamed package, and thus more than one class with the same canonical name. The behavior of programs that import from an unnamed package would be unclear in such cases (*Which* Test class should be imported?). The following JLS improvements should be considered: - Adjust the phrasing and paragraph breaks in 7.5 to make clear that the error applies for single-type-imports. - Redefine "fully-qualified name" so that classes in the unnamed package do not have one (thus ensuring that the relation from name to class is a function). - Similarly redefine "canonical name" so that classes in the unnamed package do not have one (thus ensuring that the relation is one-to-one).
19-08-2013

EVALUATION grammar confirmed JLS3, 18.1, p592
19-08-2010