From archie.cobbs at gmail.com Tue Dec 10 21:56:42 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Tue, 10 Dec 2024 15:56:42 -0600 Subject: Question re: JEP 492 specification Message-ID: The proposed JLS changes for JEP 492 are saying that this example should no longer compile*: static { class Local1 { class Local2 { public static void m() { new Local1(); // error } } } } but that seems wrong - that exampple has been allowed since JDK-8254321, and as it has nothing to do with flexible constructors, it should continue to be allowed. The JEP 492 spec says (new additions in bold): If *C* is an inner local class, then: - If *C* occurs in a static context, then *i* has no immediately enclosing instance. *Let S be the nearest static method declaration, static field declaration, or static initializer that encloses the declaration of C. If the nearest static method declaration, static field declaration, or static initializer that encloses the class instance creation expression is not S, then a compile-time error occurs.* Should there be an *Otherwise* at the beginning of the newly added sentence? (And same thing in the previous paragraph regarding anonymous classes) -Archie * See JDK-8345953 JEP 492: instantiating local classes in a different static context should not be allowed -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Tue Dec 10 22:47:35 2024 From: liangchenblue at gmail.com (Chen Liang) Date: Tue, 10 Dec 2024 16:47:35 -0600 Subject: Question re: JEP 492 specification In-Reply-To: References: Message-ID: Hi Archie, I think this rule makes sense - Local1 can capture local variables in the outer class initializer, in which case the error will be legitimate. The extra otherwise does not fix this issue. Adding a special case to allow no-capture local classes to be used in more nested static contexts seems overkill and error-prone. Chen On Tue, Dec 10, 2024, 3:57?PM Archie Cobbs wrote: > The proposed JLS changes for JEP 492 are saying that this example should > no longer compile*: > > static { > class Local1 { > class Local2 { > public static void m() { > new Local1(); // error > } > } > } > } > > but that seems wrong - that exampple has been allowed since JDK-8254321, > and as it has nothing to do with flexible constructors, it should continue > to be allowed. > > The JEP 492 spec says (new additions in bold): > > If *C* is an inner local class, then: > > - > > If *C* occurs in a static context, then *i* has no immediately > enclosing instance. *Let S be the nearest static method declaration, > static field declaration, or static initializer that encloses the > declaration of C. If the nearest static method declaration, static field > declaration, or static initializer that encloses the class instance > creation expression is not S, then a compile-time error occurs.* > > Should there be an *Otherwise* at the beginning of the newly added > sentence? (And same thing in the previous paragraph regarding anonymous > classes) > > -Archie > > * See JDK-8345953 JEP 492: > instantiating local classes in a different static context should not be > allowed > > -- > Archie L. Cobbs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Wed Dec 11 01:21:09 2024 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 11 Dec 2024 01:21:09 +0000 Subject: Question re: JEP 492 specification In-Reply-To: References: Message-ID: <406bd810-7944-4bed-b75d-7f867b5429d8@oracle.com> What Chen said. In principle, in this case, creation could be allowed because the local doesn?t capture. But when discussing the rules, we reached the conclusion that we didn?t want to specify what ?capture? meant - or classify local classes in terms of what they happen to be capturing. So, if that is what you were asking, I?d say the behavior you are observing is deliberate. Dan correctly pointed out, during an off-line discussion, that what it would be useful, in some cases, would be the ability to declare a local /static/ class. In which case you are stating that capture of variables in the enclosing context by the class is just not a possibility. In that case, the rules can be relaxed, but on a much more principed basis. Maurizio On 10/12/2024 22:47, Chen Liang wrote: > Hi Archie, > I think this rule makes sense - Local1 can capture local variables in > the outer class initializer, in which case the error will be > legitimate. The extra otherwise does not fix this issue. Adding a > special case to allow no-capture local classes to be used in more > nested static contexts seems overkill and error-prone. > > Chen > > > On Tue, Dec 10, 2024, 3:57?PM Archie Cobbs wrote: > > The proposed JLS changes for JEP 492 are saying that this example > should no longer compile*: > > ? ? static { > ? ? ? ? class Local1 { > ? ? ? ? ? ? class Local2 { > ? ? ? ? ? ? ? ? public static void m() { > ? ? ? ? ? ? ? ? ? ? new Local1();? // error > ? ? ? ? ? ? ? ? } > ? ? ? ? ? ? } > ? ? ? ? } > ? ? } > > but that seems wrong - that exampple has been allowed since > JDK-8254321, and as it has nothing to do with flexible > constructors, it should continue to be allowed. > > The JEP 492 spec says (new additions in bold): > > ? If /C/ is an inner local class, then: > > * > > If /C/ occurs in a static context, then /i/ has no immediately > enclosing instance. *Let /S/ be the nearest |static| method > declaration, |static| field declaration, or static initializer > that encloses the declaration of /C/. If the nearest |static| > method declaration, |static| field declaration, or static > initializer that encloses the class instance creation > expression is not /S/, then a compile-time error occurs.* > > Should there be an *Otherwise* at the beginning of the newly added > sentence? (And same thing in the previous paragraph regarding > anonymous classes) > > -Archie > > * See JDK-8345953 > JEP 492: instantiating local classes in a different static context > should not be allowed > > -- > Archie L. Cobbs > ​ -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Wed Dec 11 02:36:50 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Tue, 10 Dec 2024 20:36:50 -0600 Subject: Question re: JEP 492 specification In-Reply-To: <406bd810-7944-4bed-b75d-7f867b5429d8@oracle.com> References: <406bd810-7944-4bed-b75d-7f867b5429d8@oracle.com> Message-ID: OK thanks to both of you for clarifying this. I agree it's good to keep the rule simple. I realize now I was kind of thrown off by the lack of connection with flexible constructors and the fact that this compiles in (e.g.) JDK 17, but that was because I didn't read the little note carefully enough... *This missing condition is a bugfix for extensions introduced in JEP 395.* Thanks, -Archie On Tue, Dec 10, 2024 at 7:21?PM Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > What Chen said. > > In principle, in this case, creation could be allowed because the local > doesn?t capture. But when discussing the rules, we reached the conclusion > that we didn?t want to specify what ?capture? meant - or classify local > classes in terms of what they happen to be capturing. So, if that is what > you were asking, I?d say the behavior you are observing is deliberate. > > Dan correctly pointed out, during an off-line discussion, that what it > would be useful, in some cases, would be the ability to declare a local > *static* class. In which case you are stating that capture of variables > in the enclosing context by the class is just not a possibility. In that > case, the rules can be relaxed, but on a much more principed basis. > > Maurizio > > On 10/12/2024 22:47, Chen Liang wrote: > > Hi Archie, > I think this rule makes sense - Local1 can capture local variables in the > outer class initializer, in which case the error will be legitimate. The > extra otherwise does not fix this issue. Adding a special case to allow > no-capture local classes to be used in more nested static contexts seems > overkill and error-prone. > > Chen > > On Tue, Dec 10, 2024, 3:57?PM Archie Cobbs wrote: > >> The proposed JLS changes for JEP 492 are saying that this example should >> no longer compile*: >> >> static { >> class Local1 { >> class Local2 { >> public static void m() { >> new Local1(); // error >> } >> } >> } >> } >> >> but that seems wrong - that exampple has been allowed since JDK-8254321, >> and as it has nothing to do with flexible constructors, it should continue >> to be allowed. >> >> The JEP 492 spec says (new additions in bold): >> >> If *C* is an inner local class, then: >> >> - >> >> If *C* occurs in a static context, then *i* has no immediately >> enclosing instance. *Let S be the nearest static method declaration, >> static field declaration, or static initializer that encloses the >> declaration of C. If the nearest static method declaration, static field >> declaration, or static initializer that encloses the class instance >> creation expression is not S, then a compile-time error occurs.* >> >> Should there be an *Otherwise* at the beginning of the newly added >> sentence? (And same thing in the previous paragraph regarding anonymous >> classes) >> >> -Archie >> >> * See JDK-8345953 JEP 492: >> instantiating local classes in a different static context should not be >> allowed >> >> -- >> Archie L. Cobbs >> > ​ > -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Wed Dec 11 20:25:08 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Wed, 11 Dec 2024 14:25:08 -0600 Subject: JDK-8300691 - final variables in for loop headers should accept updates Message-ID: Dear Spec Experts, There is a (small) language change under consideration on amber-dev, and opinions have been expressed in multiple directions, so I'm turning to this list for hopefully some authoritative adjudication. The idea is: allow loop variables declared in basic (old style) for() loops to be captured in the body of the loop as long as they are not reassigned in the body of the loop, even though they might be reassigned in the loop step: for (int i = 1; i <= 3; i++) { Runnable r = () -> System.out.println(i); // allow this } Long discussion starts here (continues into October): https://mail.openjdk.org/pipermail/amber-dev/2024-September/008921.html Here's what has been drafted so far (all subject to improvement of course): Bug: https://bugs.openjdk.org/browse/JDK-8341782 CSR: https://bugs.openjdk.org/browse/JDK-8341783 JEP: https://bugs.openjdk.org/browse/JDK-8341785 JLS: https://bugs.openjdk.org/browse/JDK-8341786 PR: https://github.com/openjdk/jdk/pull/21415 Just to be clear, I know it looks like I've got a lot personally invested in this, but honestly I don't care about the outcome. Yes I think this would be a nice tweak, but it's not my decision. Instead, the items listed above are there to create a tangible basis for making such a decision. I am really just trying to knock this item off my to-do list one way or the other (scrubbing the to-do list is a favorite year-end activity). Let me know your collective thoughts, ideally one of: ? Proceed ? Reject ? Shelve it for later Thanks! -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From kevinb9n at gmail.com Wed Dec 11 22:36:44 2024 From: kevinb9n at gmail.com (Kevin Bourrillion) Date: Wed, 11 Dec 2024 14:36:44 -0800 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: Message-ID: [note: I'm a new Oracle/JPG member, though this is coming from my personal mail. I'm not speaking for the team though, just myself.] Thanks very much for all your work on this, and your whole approach to it all. It is pretty easy to classify this as a "quality-of-life" improvement, and I recall that it was very well-received on reddit. Since its main effect is to let something work that otherwise would not work, and would force busywork on the poor user, I think we'd be unlikely to get complaints about it! That said, I'd like to try to summarize the best argument against the change (that I know of) anyway. To be clear, I don't think the team currently views this argument as outweighing the benefits, but I wanted to put it out there in case it sparks any further realizations out there. I also apologize that it's not short! A little background first: What exactly gets captured when a lambda captures something? It has always been of a *value*, never a whole variable. However, there's a trick, because there is an invisible `this.` in front of any *field* mentioned, and it is *that* value that is captured. This creates the illusion that maybe it really is a variable being captured. So, to the user it might feel like there are two different rules in effect for two different kinds of variables. Fortunately, the protections against capturing a non-effectively-final local variable prevent that distinction from mattering! So users don't have to be troubled by this quirk. The enhanced for loop steps right up to the edge of this line. It seems like *one* variable that is changing, right? But our allowing it to be marked `final` is a statement that no, it really is a fresh variable each time through the loop. And I claim that was sensible: there is nothing you can do to that variable inside your loop body that has any chance of affecting its value on the next trip through the loop. So it is *cleaner* to conceptualize this as a new variable every time (as if its declaration had been inside the braces). All that is *not* the case for the classic for loop. Since the update clause in the header is very often (usually!) an increment statement, your changes in the body can certainly affect the next iteration. Obviously your proposal excludes this case, as it must, but I claim that the *general* fact remains: that to understand classic for loops we must be mindful that it really is just one reused variable we're looking at. None of this actually sinks your proposal by itself! But it does mean that I would characterize your proposal as creating a special case: we feel it's okay to allow it because we find it sufficiently *implausible* that the user meant to capture the variable. My concern is that now there will be some code out there that *appears* to proclaim to the reader "hey, it's values, not variables, that get captured". (Ironically, *it is!*, ha ha, so you'd think this is fine. But as discussed a moment ago, the point is that today it's a "distinction without a difference" and it wouldn't be anymore.) I do fully get that not being able to refer to a loop variable in a lambda is plain annoying. The next time I hit this in my own coding I will feel as annoyed as anyone. :-) For what it's worth I see it as "just annoyance", though, which has only a self-contained incremental cost each time you hit it. I find it easy to accept costs like that, compared to the more unknowable costs of opening up cracks in the user's clean and simple conceptual model of how the language works (but that's me and my nature). And I think that a reasonable reaction to that annoyance is "oh, right, this is annoying, but at least it makes sense: this *is* a mutating variable, and Java doesn't allow those across the board because they create ambiguity." It at least doesn't teach a wrong lesson. [Aside from all that, the second issue has been "are we sure this is really the *one* exception to the usual rule that we need, and then we're done?", but I don't have anything new to say about that.] Having spelled that out, it is only for everyone's consideration. If the benefits are considered to outweigh it, then we should go ahead and I'll still be a happy camper. On Wed, Dec 11, 2024 at 12:25?PM Archie Cobbs wrote: > Dear Spec Experts, > > There is a (small) language change under consideration on amber-dev, and > opinions have been expressed in multiple directions, so I'm turning to this > list for hopefully some authoritative adjudication. > > The idea is: allow loop variables declared in basic (old style) for() > loops to be captured in the body of the loop as long as they are not > reassigned in the body of the loop, even though they might be reassigned in > the loop step: > > for (int i = 1; i <= 3; i++) { > Runnable r = () -> System.out.println(i); // allow this > } > > Long discussion starts here (continues into October): > https://mail.openjdk.org/pipermail/amber-dev/2024-September/008921.html > > Here's what has been drafted so far (all subject to improvement of course): > > Bug: https://bugs.openjdk.org/browse/JDK-8341782 > CSR: https://bugs.openjdk.org/browse/JDK-8341783 > JEP: https://bugs.openjdk.org/browse/JDK-8341785 > JLS: https://bugs.openjdk.org/browse/JDK-8341786 > PR: https://github.com/openjdk/jdk/pull/21415 > > Just to be clear, I know it looks like I've got a lot personally invested > in this, but honestly I don't care about the outcome. Yes I think this > would be a nice tweak, but it's not my decision. Instead, the items listed > above are there to create a tangible basis for making such a decision. I am > really just trying to knock this item off my to-do list one way or the > other (scrubbing the to-do list is a favorite year-end activity). > > Let me know your collective thoughts, ideally one of: ? Proceed ? Reject ? > Shelve it for later > > Thanks! > -Archie > > -- > Archie L. Cobbs > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Thu Dec 19 15:18:36 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Thu, 19 Dec 2024 09:18:36 -0600 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: Message-ID: On Wed, Dec 11, 2024 at 2:25?PM Archie Cobbs wrote: > There is a (small) language change under consideration on amber-dev, and > opinions have been expressed in multiple directions, so I'm turning to this > list for hopefully some authoritative adjudication. > Since I didn't hear an overwhelming roar of approval, I'll shelve this for now. The issues and PR will still be there if/when we want to take this up again in the future. Thanks, -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Sun Dec 29 17:30:26 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 29 Dec 2024 12:30:26 -0500 Subject: Fwd: String templates - JEP-459, JEP-465 In-Reply-To: References: Message-ID: <0330a831-bf07-4cf4-81bd-4f7ec7496f45@oracle.com> The following was received on amber-spec-comments. The opinion expressed here (which can be paraphrased as "why don't you just do string interpolation, it's safe and simple") is a familiar one, and one which has been discussed over and over.? The belief that there are "no security concerns" with string interpolation is incorrect, and "just do string interpolation" remains an anti-goal. The author here might be correct that the intersection of "acceptably secure" and "acceptably complex" is empty; in this case we will do nothing.? But we are continuing to explore this space to find something that balances all the concerns. -------- Forwarded Message -------- Subject: String templates - JEP-459, JEP-465 Date: Sun, 22 Dec 2024 01:27:16 +0100 From: Mariusz Lotko To: amber-spec-comments at openjdk.java.net Good evening, I read all three JEPs of String Templates and I'm a bit surprised that we need such a complicated feature. I bet that most Java developers simply _expects_? simple string interpolation, that they will be able to replace not-quite-readable string concatenations like: ??? "This is " + some.strange().callsWith("an argument") + " the end" with something like (I like JS version the most) ??? `This is ${some.strange().callsWith("an argument")} the end` or ??? ``` ??? This is the multilne version ?? ${some.strange().callsWith("an argument")} ?? the multiline end ?? ``` At compiler level that would be "simply" replace to old-good contatenation implementation which is StringBuilder calls. No security concerns (other than with current + operator), no (hidden) runtime penalties like the proposed FMT feature has to introduce. "String Templates" as language feature opened for externding by the libraries seem to me quite complicated. The benefit that we provide templates built into the language does not seem to be attractive - why should I use built-in templates instead of 3rd party Velocity/JTwig/whatever else? Best regards, Mariusz Lotko -------------- next part -------------- An HTML attachment was scrubbed... URL: