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