javac bug: defender method processing

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Oct 28 01:31:58 PDT 2010


On 28/10/10 06:38, David Holmes wrote:
> I would think that JLS 7.4.2 is most relevant here - Unnamed Packages.
> In short in depends on the implementation as to how many unnamed
> packages exist (there must be at least one) and what form they take.
> Using the example in the JLS of an un-named package per directory,
> Brian's example, and David's, need not compile.
>    
I agree that this has nothing to do with lambda. A simpler test case 
also fails with both jdk 6/7:

src/A.java

public class A {}

src/pkg/B.java

package pkg;

public class B extends A {}


You need A to be in a named package here.

Maurizio

> David Holmes
>
> Jonathan Gibbons said the following on 10/28/10 14:53:
>    
>> David,
>>      
>>> Unfortunately, a quick test shows that javac doesn't seem to fully
>>> implement JLS 6.7 in regards to unnamed packages
>>>        
>> 6.7 simply defines Fully Qualified Names and Canonical Names. It says
>> nothing about the meaning of names. For that you need to read 6.5, and
>> 6.5.5.1 in particular:
>>
>> http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.5.5.1
>>
>> If a type name consists of a single /Identifier/, then the identifier
>> must occur in the scope of exactly one visible declaration of a type
>> with this name, or a compile-time error occurs. The meaning of the type
>> name is that type.
>>
>> -- Jon
>>
>>
>>
>>
>> On 10/27/2010 06:45 PM, David Schlosnagle wrote:
>>      
>>> 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