Bug 317212

Summary: [compiler] Illegal permission to invoke the constructor of a member class of an inaccessible type.
Product: [Eclipse Project] JDT Reporter: Christian Zoller <eclipse>
Component: CoreAssignee: Srikanth Sankaran <srikanth_sankaran>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: amj87.iitr, jarthana, Olivier_Thomann
Version: 3.6Flags: jarthana: review+
Target Milestone: 3.7 M1   
Hardware: PC   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
Example code
none
example with obvious corrections
none
Patch under test
none
Revised patch none

Description Christian Zoller CLA 2010-06-17 12:26:47 EDT
Build Identifier: 20100218-1602

There is no compiler error, when you call the constructor of a member class of an inaccessible enclosing class. This violates JLS § 6.6.1, which says that "A member (class, interface, field, or method) of a reference (class, interface, or array) type or a constructor of a class type is accessible only if the type is accessible [...]"

Reproducible: Always

Steps to Reproduce:
1. Write a package-private class A with a public member class M.
2. Write public class B in the same package, that has a public method m() with return type A.
3. Write a class C in another package that calls the constructor of M at the return value of B.m()
Comment 1 Christian Zoller CLA 2010-06-17 12:33:24 EDT
Created attachment 172139 [details]
Example code
Comment 2 Olivier Thomann CLA 2010-06-17 12:36:32 EDT
Potential 3.6.1 candidate depending on the risk of the fix.
Comment 3 Christian Zoller CLA 2010-06-17 12:37:00 EDT
Comment on attachment 172139 [details]
Example code

> B.m().new M();

This line should produce a compiler error according to JLS § 6.6.1, but does nut.

=> http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.1
Comment 4 Stephan Herrmann CLA 2010-06-18 08:17:44 EDT
Created attachment 172209 [details]
example with obvious corrections

The same example code with two tiny obvious corrections:
- return type of m() must be A, not B
- added missing import in C

Interestingly, javac (1.6.0_18) gives a pretty strange error:

p1/C.java:6: package p0.A does not exist
        B.m().new M();
                  ^
1 error

I'm sure the JDT can do better :)
Comment 5 Christian Zoller CLA 2010-06-18 08:23:43 EDT
> The same example code with two tiny obvious corrections:
> - return type of m() must be A, not B
> - added missing import in C

Thank you. I was a bit in a hurry when I wrote that. Sorry.
Comment 6 Srikanth Sankaran CLA 2010-06-22 00:25:22 EDT
Reproduced on HEAD. See that for method invocations and
field references under similar conditions, we do issue the
correct error. The problem seems to be specific to 
constructors.
Comment 7 Srikanth Sankaran CLA 2010-06-22 01:50:41 EDT
Also broken is:

public class B {
    public static A m() {
        return new A();
    }
    private static class A {
        public class M {
            public M() {}
        }
}
}

class C {
    public static void main(String[] args) {
        B.m().new M();  // no error here 
    }
}
Comment 8 Srikanth Sankaran CLA 2010-06-22 02:33:21 EDT
Created attachment 172386 [details]
Patch under test
Comment 9 Srikanth Sankaran CLA 2010-06-22 04:44:05 EDT
Created attachment 172392 [details]
Revised patch

Earlier patch had a problem, like this one better.
Comment 10 Jay Arthanareeswaran CLA 2010-06-23 02:46:53 EDT
Patch looks good to me.
Comment 11 Srikanth Sankaran CLA 2010-06-23 02:58:30 EDT
Fixed an unneeded set of parenthesis pointed out by
Jay and released patch in HEAD for 3.7 M1
Comment 12 Ayushman Jain CLA 2010-08-03 08:09:06 EDT
Verified for 3.7M1 using build I20100802-1800.

Note that the quick fix given here is "change visibility of m() to public", which is not correct. It should instead offer changing visibility of A to public. Raised bug 321582 for that.