javac bug: defender method processing

David Schlosnagle schlosna at gmail.com
Wed Oct 27 18:45:16 PDT 2010


Brian,

I don't believe this problem is specific to lambda, it is purely a
combination of the interactions between the default visibility of the
Impl type JLS 6.6.1 [1] and unnamed packages JLS 7.4.2 [2]. If you
were to make the Impl class public, I would think you should be able
to reference it using the fully qualified name 'Impl' per JLS 6.7 [3]:
    The fully qualified name of a top level class or top level
interface that is declared in an unnamed package is the simple name of
the class or interface.

Unfortunately, a quick test shows that javac doesn't seem to fully
implement JLS 6.7 in regards to unnamed packages, all the more reason
to not use unnamed packages!

$ javac -fullversion
javac full version "1.7.0-internal-david_2010_07_23_16_08-b00"

$ cat Impl.java
public class Impl {}

$ cat test/TestUnnamedPackageVisibility.java
package test;
public class TestUnnamedPackageVisibility {
    public static void main(String... args) {
        System.out.println(Impl.class);
    }
}

$ find . -name "*.java"
./Impl.java
./test/TestUnnamedPackageVisibility.java

$ javac -d ../bin/ Impl.java test/TestUnnamedPackageVisibility.java
test/TestUnnamedPackageVisibility.java:4: cannot find symbol
        System.out.println(Impl.class);
                           ^
  symbol:   class Impl
  location: class TestUnnamedPackageVisibility
1 error


Also, Java 1.4 removed the ability to explicitly import a type from an
unnamed package (per section 8 of the Java 1.4 compatibility [4]):
    The compiler now rejects import statements that import a type from the
    unnamed namespace. Previous versions of the compiler would accept such
    import declarations, even though they were arguably not allowed by the
    language (because the type name appearing in the import clause is not in
    scope). The specification is being clarified to state clearly that you
    cannot have a simple name in an import statement, nor can you import from
    the unnamed namespace.


References:
[1]: http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.1
[2]: http://java.sun.com/docs/books/jls/third_edition/html/packages.html#7.4.2
[3]: http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.7
[4]: http://java.sun.com/javase/compatibility_j2se1.4.html

- Dave


On Wed, Oct 27, 2010 at 5:43 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
>
> I created this file:
>
> src/Impl.java (no package)
>
> class Impl {
>     public static int one() { return 1 };
> }
>
> and this test file:
>
> src/junit/SimpleDefenderTest.java:
>
> package junit;
>
> import junit.framework.TestCase;
>
> public class SimpleDefenderTest extends TestCase {
>     private static interface A {
>         public extension int get() default Impl.one;
>     }
>
>     private static class C implements A {
>     }
>
>     public void testSimpleWeave() {
>         C c = new C();
>         assertEquals(1, c.get());
>     }
> }
>
>
> It failed to compile, with this error:
>
>     [javac] src/junit/SimpleDefenderTest.java:7: cannot find symbol
>     [javac]         public extension int get() default Impl.one;
>     [javac]                              ^
>     [javac]   symbol:   variable Impl
>     [javac]   location: interface A
>     [javac] 1 error
>
>
> The problem seems to be either that Impl was in the empty package, or maybe
> that it was just in another package.  I moved it to the same package and it
> worked.
>
>
>
>


More information about the lambda-dev mailing list