From rotanolexandr842 at gmail.com Mon Aug 26 12:28:58 2024 From: rotanolexandr842 at gmail.com (Olexandr Rotan) Date: Mon, 26 Aug 2024 15:28:58 +0300 Subject: Selaed classes cant permit private classes Message-ID: Hello. Recently, I have started a new project to explore Babylon code reflection API (LInq), and thought that using sealed classes to represent operand type would be really suitable (function calls, column refs etc.). However, I want to only expose one interface/abstract class for each of those types, while actual implementations are private classes inside sealed classes. However, when I tried to compile something like this (simplified for brevity): sealed class Tmp permits Tmp.A { private static final class A extends Tmp { } } I got following error: error: A has private access in Tmp Is this behaviour expected or not? (I would assume second since intellij code analysis didn't mark this as error) If it's later, I would ask some JDK member to file a bug report (I noticed that they are processed faster then non-member requests), and I will try to fix this. If it`s premier, then what is the motivation behind this? -------------- next part -------------- An HTML attachment was scrubbed... URL: From pavel.rappo at oracle.com Mon Aug 26 13:00:46 2024 From: pavel.rappo at oracle.com (Pavel Rappo) Date: Mon, 26 Aug 2024 13:00:46 +0000 Subject: Selaed classes cant permit private classes In-Reply-To: References: Message-ID: <446E5034-38F3-4368-9F1C-8DEDD6F95398@oracle.com> On a cursory search, I haven't found anything in JLS on that. Yet, a similar example is mentioned as if it were compilable here (it isn't): https://openjdk.org/jeps/409#Future-Work Interestingly, if you wrap your example into a class/interface and add `static` to Tmp, the example will compile. -Pavel > On 26 Aug 2024, at 13:28, Olexandr Rotan wrote: > > Hello. Recently, I have started a new project to explore Babylon code reflection API (LInq), and thought that using sealed classes to represent operand type would be really suitable (function calls, column refs etc.). However, I want to only expose one interface/abstract class for each of those types, while actual implementations are private classes inside sealed classes. However, when I tried to compile something like this (simplified for brevity): > > sealed class Tmp permits Tmp.A { > > private static final class A extends Tmp { > } > } > > > I got following error: > error: A has private access in Tmp > > > Is this behaviour expected or not? > (I would assume second since intellij code analysis didn't mark this as error) > > If it's later, I would ask some JDK member to file a bug report (I noticed that they > are processed faster then non-member requests), and I will try to fix this. If it`s > premier, then what is the motivation behind this? > > From jan.lahoda at oracle.com Mon Aug 26 13:42:51 2024 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Mon, 26 Aug 2024 15:42:51 +0200 Subject: Selaed classes cant permit private classes In-Reply-To: References: Message-ID: <015aa693-8d91-4973-9933-7cd6d7546112@oracle.com> Hi Olexandr, Thanks for the report. I've filled: https://bugs.openjdk.org/browse/JDK-8338981 Jan On 26. 08. 24 14:28, Olexandr Rotan wrote: > Hello. Recently, I have started a new project to explore Babylon code > reflection API (LInq), and thought that using sealed classes to > represent operand type would?be really suitable (function calls, > column refs etc.). However, I want to only expose one > interface/abstract class for each of those types, while actual > implementations are private classes inside sealed classes. However, > when I tried to compile something like this (simplified for brevity): > > sealed class Tmppermits Tmp.A { > > private static final class Aextends Tmp { > } > } > I got following error: > error: A has private access in Tmp > Is this behaviour expected or not? (I would assume second since > intellij code analysis didn't mark this as error) If it's later, I > would ask some JDK member to file a bug report (I noticed that they > are processed faster then non-member requests), and I will try to fix > this. If it`s premier, then what is the motivation behind this? -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Mon Aug 26 13:44:31 2024 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 26 Aug 2024 14:44:31 +0100 Subject: Selaed classes cant permit private classes In-Reply-To: References: Message-ID: <4856dfb1-e0a1-424d-b90d-203c39b596a8@oracle.com> Hi, I?m not sure whether the error you get is legit or not, but I observe that it?s not just about sealed classes - e.g. something like |class Tmp| results in the same behavior. I think this is due to JLS 6.3: > The scope of a declaration of a member |m| declared in or inherited by > a class or interface C (?8.2 > , > ?9.2 > ) > is the entire body of C, including any nested class or interface > declarations. If C is a record class, then the scope of |m| > additionally includes the header of the record declaration of C. > That is, an ?extends? or ?permits? clause is not really type-checked as if inside the body of class C. This results in the accessibility problem you point out (which might or might not be a compiler glitch, I don?t think the JLS is crystal clear on how Tmp.A should be checked). That said? back to your immediate problem - whenever you have nested classes extending from a toplevel class, you can just omit ?permits? and leave it to javac, like so: |sealed class Tmp { private static final class A extends Tmp { ... } // ok } | This should allow what you want to do. Maurizio On 26/08/2024 13:28, Olexandr Rotan wrote: > Hello. Recently, I have started a new project to explore Babylon code > reflection API (LInq), and thought that using sealed classes to > represent operand type would?be really suitable (function calls, > column refs etc.). However, I want to only expose one > interface/abstract class for each of those types, while actual > implementations are private classes inside sealed classes. However, > when I tried to compile something like this (simplified for brevity): > > sealed class Tmppermits Tmp.A { > > private static final class Aextends Tmp { > } > } > I got following error: > error: A has private access in Tmp > Is this behaviour expected or not? (I would assume second since > intellij code analysis didn't mark this as error) If it's later, I > would ask some JDK member to file a bug report (I noticed that they > are processed faster then non-member requests), and I will try to fix > this. If it`s premier, then what is the motivation behind this? ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From rotanolexandr842 at gmail.com Mon Aug 26 13:44:27 2024 From: rotanolexandr842 at gmail.com (Olexandr Rotan) Date: Mon, 26 Aug 2024 16:44:27 +0300 Subject: Selaed classes cant permit private classes In-Reply-To: <015aa693-8d91-4973-9933-7cd6d7546112@oracle.com> References: <015aa693-8d91-4973-9933-7cd6d7546112@oracle.com> Message-ID: Hi Jan, thank you very much. I`ll look into the issue later today On Mon, Aug 26, 2024 at 4:43?PM Jan Lahoda wrote: > Hi Olexandr, > > > Thanks for the report. I've filled: > https://bugs.openjdk.org/browse/JDK-8338981 > > > Jan > > > On 26. 08. 24 14:28, Olexandr Rotan wrote: > > Hello. Recently, I have started a new project to explore Babylon code > reflection API (LInq), and thought that using sealed classes to represent > operand type would be really suitable (function calls, column refs etc.). > However, I want to only expose one interface/abstract class for each of > those types, while actual implementations are private classes inside sealed > classes. However, when I tried to compile something like this (simplified > for brevity): > > sealed class Tmp permits Tmp.A { > > private static final class A extends Tmp { > } > } > > I got following error: > > error: A has private access in Tmp > > Is this behaviour expected or not? > (I would assume second since intellij code analysis didn't mark this as error) > > If it's later, I would ask some JDK member to file a bug report (I noticed that they > are processed faster then non-member requests), and I will try to fix this. If it`s > premier, then what is the motivation behind this? > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Mon Aug 26 13:51:31 2024 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 26 Aug 2024 14:51:31 +0100 Subject: Selaed classes cant permit private classes In-Reply-To: <4856dfb1-e0a1-424d-b90d-203c39b596a8@oracle.com> References: <4856dfb1-e0a1-424d-b90d-203c39b596a8@oracle.com> Message-ID: <54d38287-d6c9-44b0-8e5b-1af98bda06ca@oracle.com> On 26/08/2024 14:44, Maurizio Cimadamore wrote: > That is, an ?extends? or ?permits? clause is not really type-checked > as if inside the body of class C. This results in the accessibility > problem you point out (which might or might not be a compiler glitch, > I don?t think the JLS is crystal clear on how Tmp.A should be checked). I stand corrected - see JLS 6.6: > A member (class, interface, field, or method) of a class, interface, > type parameter, or reference type, or a constructor of a class, is > accessible only if (i) the class, interface, type parameter, or > reference type is accessible, and (ii) the member or constructor is > declared to permit access: > [...] > > * > > ?Otherwise, the member or constructor is declared |private|. > Access is permitted only when one of the following is true: > > o > > Access occurs from within the body of the top level class or > interface that encloses the declaration of the member or > constructor. > > o Access occurs in the |permits| clause of the top level class > or interface that encloses the declaration of the member. > o > > Access occurs in the record component list of the top level > record class that encloses the declaration of the member. > So, there's special accessibility pleads for "permits" clauses. So yes, this is a javac bug. I've added some comments to JDK-8338981. Maurizio -------------- next part -------------- An HTML attachment was scrubbed... URL: From rotanolexandr842 at gmail.com Mon Aug 26 14:09:15 2024 From: rotanolexandr842 at gmail.com (Olexandr Rotan) Date: Mon, 26 Aug 2024 17:09:15 +0300 Subject: Selaed classes cant permit private classes In-Reply-To: <54d38287-d6c9-44b0-8e5b-1af98bda06ca@oracle.com> References: <4856dfb1-e0a1-424d-b90d-203c39b596a8@oracle.com> <54d38287-d6c9-44b0-8e5b-1af98bda06ca@oracle.com> Message-ID: So there is a special case for permits clause, but what about extends clause? Should I also look into it, or, formally, this is a different issue that requires (arguably) JLS change? On Mon, Aug 26, 2024 at 4:51?PM Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > > On 26/08/2024 14:44, Maurizio Cimadamore wrote: > > That is, an ?extends? or ?permits? clause is not really type-checked as if > inside the body of class C. This results in the accessibility problem you > point out (which might or might not be a compiler glitch, I don?t think the > JLS is crystal clear on how Tmp.A should be checked). > > I stand corrected - see JLS 6.6: > > A member (class, interface, field, or method) of a class, interface, type > parameter, or reference type, or a constructor of a class, is accessible > only if (i) the class, interface, type parameter, or reference type is > accessible, and (ii) the member or constructor is declared to permit > access: > [...] > > - > > Otherwise, the member or constructor is declared private. Access is > permitted only when one of the following is true: > - > > Access occurs from within the body of the top level class or > interface that encloses the declaration of the member or constructor. > - Access occurs in the permits clause of the top level class or > interface that encloses the declaration of the member. > - > > Access occurs in the record component list of the top level record > class that encloses the declaration of the member. > > So, there's special accessibility pleads for "permits" clauses. So yes, > this is a javac bug. > > I've added some comments to JDK-8338981. > > Maurizio > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Mon Aug 26 14:14:40 2024 From: vicente.romero at oracle.com (Vicente Romero) Date: Mon, 26 Aug 2024 10:14:40 -0400 Subject: Selaed classes cant permit private classes In-Reply-To: References: <4856dfb1-e0a1-424d-b90d-203c39b596a8@oracle.com> <54d38287-d6c9-44b0-8e5b-1af98bda06ca@oracle.com> Message-ID: <1a6b6a0b-691e-4599-9835-54812a0d165a@oracle.com> Hi Olexandr, I will take a look at this issue, in the meantime as Maurizio commented if you don't specify the permits clause the compiler should be able to infer it for you, Thanks, Vicente On 8/26/24 10:09, Olexandr Rotan wrote: > So there is a special case for permits clause, but what about extends > clause? Should I also look into?it, or, formally, this is a different > issue that requires (arguably) JLS change? > > On Mon, Aug 26, 2024 at 4:51?PM Maurizio Cimadamore > wrote: > > > On 26/08/2024 14:44, Maurizio Cimadamore wrote: >> That is, an ?extends? or ?permits? clause is not really >> type-checked as if inside the body of class C. This results in >> the accessibility problem you point out (which might or might not >> be a compiler glitch, I don?t think the JLS is crystal clear on >> how Tmp.A should be checked). > > I stand corrected - see JLS 6.6: > >> A member (class, interface, field, or method) of a class, >> interface, type parameter, or reference type, or a constructor of >> a class, is accessible only if (i) the class, interface, type >> parameter, or reference type is accessible, and (ii) the member >> or constructor is declared to permit access: >> [...] >> >> * >> >> ?Otherwise, the member or constructor is declared |private|. >> Access is permitted only when one of the following is true: >> >> o >> >> Access occurs from within the body of the top level class >> or interface that encloses the declaration of the member >> or constructor. >> >> o Access occurs in the |permits| clause of the top level >> class or interface that encloses the declaration of the >> member. >> o >> >> Access occurs in the record component list of the top >> level record class that encloses the declaration of the >> member. >> > So, there's special accessibility pleads for "permits" clauses. So > yes, this is a javac bug. > > I've added some comments to JDK-8338981. > > Maurizio > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Mon Aug 26 18:32:12 2024 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 26 Aug 2024 19:32:12 +0100 Subject: Selaed classes cant permit private classes In-Reply-To: References: <4856dfb1-e0a1-424d-b90d-203c39b596a8@oracle.com> <54d38287-d6c9-44b0-8e5b-1af98bda06ca@oracle.com> Message-ID: For "extends" at the class level, I think in reality you end up with cyclic inheritance, so there's not much to do. For "extends" in a type-parameter, that's a valid question - althugh, if you think about it, having a class with a type-variable whose bound is a _private_ member of that class, seems not too useful (the only place where you can parameterize instances of that class correctly is that class itself). Maurizio On 26/08/2024 15:09, Olexandr Rotan wrote: > So there is a special case for permits clause, but what about extends > clause? Should I also look into?it, or, formally, this is a different > issue that requires (arguably) JLS change? > > On Mon, Aug 26, 2024 at 4:51?PM Maurizio Cimadamore > wrote: > > > On 26/08/2024 14:44, Maurizio Cimadamore wrote: >> That is, an ?extends? or ?permits? clause is not really >> type-checked as if inside the body of class C. This results in >> the accessibility problem you point out (which might or might not >> be a compiler glitch, I don?t think the JLS is crystal clear on >> how Tmp.A should be checked). > > I stand corrected - see JLS 6.6: > >> A member (class, interface, field, or method) of a class, >> interface, type parameter, or reference type, or a constructor of >> a class, is accessible only if (i) the class, interface, type >> parameter, or reference type is accessible, and (ii) the member >> or constructor is declared to permit access: >> [...] >> >> * >> >> ?Otherwise, the member or constructor is declared |private|. >> Access is permitted only when one of the following is true: >> >> o >> >> Access occurs from within the body of the top level class >> or interface that encloses the declaration of the member >> or constructor. >> >> o Access occurs in the |permits| clause of the top level >> class or interface that encloses the declaration of the >> member. >> o >> >> Access occurs in the record component list of the top >> level record class that encloses the declaration of the >> member. >> > So, there's special accessibility pleads for "permits" clauses. So > yes, this is a javac bug. > > I've added some comments to JDK-8338981. > > Maurizio > -------------- next part -------------- An HTML attachment was scrubbed... URL: