From john.r.rose at oracle.com Tue Oct 1 00:02:14 2019 From: john.r.rose at oracle.com (John Rose) Date: Mon, 30 Sep 2019 17:02:14 -0700 Subject: JDK-8227870 - Escape Sequences For Line Continuation and White Space (Preview) In-Reply-To: <668eeaf5-8b87-5513-4a45-2850aaab333b@oracle.com> References: <33968389-E102-4778-8BB8-DDF2D2A30416@oracle.com> <5c358eb7-451a-ce14-8800-171903b9b277@oracle.com> <668eeaf5-8b87-5513-4a45-2850aaab333b@oracle.com> Message-ID: <4A085A9A-DB22-4161-BB3E-AB1E50A92D71@oracle.com> On Sep 30, 2019, at 9:05 AM, Maurizio Cimadamore wrote: > > ``` > Add text blocks to the Java language. A text block is a multi-line string literal that avoids the need for most escape sequences, automatically formats the string in a predictable way, and gives the developer control over format when desired. This is a preview language feature in JDK 13. > ``` > > Now, I get the subtle distinction between multi-line in the source and multi-line in the result value - but it's subtle, and I think the JEP should at least be made clearer in that respect. > I like this suggestion. Looking closely at the phrase "multi-line string literal?, I think it is ambiguous to parse. So, ?(multi-line string) literal? would be ?a literal for a string with newlines in it?, which we have today. And ?multi-line (string literal)? would be ?a string literal whose syntax contains line breaks?. The latter is the new thing. The JEP should probably explain the difference between the former and the latter, one way or another, and either use less ambiguous language or disambiguate some other way (via an explanation). The benefit of an updated *string literal* that has *line breaks* is that the source form of the string can be arranged for better readability. It?s not like we can express new sequences of characters; it?s about prettier literals. And that, in turn, amply motivates the latest proposals (IMO), since supporting \s and \ gives users some very useful control over the esthetics of their literals. The rules for stripping leading blanks are very good for controlling the horizontal position of a literal?s contents, but they don?t help (and sometimes hurt) working with very long lines. For that, you need a directive to paste two source lines together in one payload line, just as \n splits one source line into two payload lines. In the end, most source newlines will (and should) correspond to payload newlines, but there will always be cases where one source line should be broken (with \n) into two payload lines and vice versa (with \). These two cases are roughly symmetrical with each other. ? John From john.r.rose at oracle.com Tue Oct 1 01:30:18 2019 From: john.r.rose at oracle.com (John Rose) Date: Mon, 30 Sep 2019 18:30:18 -0700 Subject: JDK-8227870 - Escape Sequences For Line Continuation and White Space (Preview) In-Reply-To: <33968389-E102-4778-8BB8-DDF2D2A30416@oracle.com> References: <33968389-E102-4778-8BB8-DDF2D2A30416@oracle.com> Message-ID: <9B49D074-D44F-4738-AF69-6844CF90EBDC@oracle.com> On Sep 30, 2019, at 4:45 AM, Jim Laskey wrote: > > During the discussion on Text Blocks, several of you stated a need for a line continuation construct. I have since created a CSR to propose the creation of two new escape sequences: \ and \s. > > https://bugs.openjdk.java.net/browse/JDK-8227870 > One observation: Some traditional uses of \LT, as in C macros, makefiles, and shell, line up the \ characters in a single column as a sort of right-hand fence: foo bar \ baz \ bat This can be done only in settings where the spaces before the \ are treated as ancillary format, not payload characters. We could make a similar rule for multi-line literals, by saying that unescaped spaces *before* the \LT are also deleted when the \LT sequence is deleted. In other words, the \ at the end of the line is *not* a fence that transforms the So: var x = ??? foo bar \ baz \ bat \ ???; assert x.equals(?foo bar baz bat?); The single space before baz and the three spaces before bat are the left-hand leading spaces, not the ancillary spaces before the \ characters. If some of those trailing spaces are desirable, then \s can be used to make a fence that saves them from stripping. var x = ??? foo bar\s \ baz \s \ bat\s \ ???; assert x.equals(?foo bar baz bat ?); This rule decouples the two functions of \LT in the current proposal: (1) It joins lines, and (2) it creates a fence which makes previously ancillary spaces into real payload spaces. These are distinct jobs and should not be conflated. I think it?s a small but real improvement to separate the jobs, and allow \s to handle (2) and \LT to handle only (1). ? John P.S. A variation of the above suggestion, probably less preferable, would delete spaces both *before* and *after* \LT, leading to this: var x = ??? foo bar \ baz \ bat \ ???; assert x.equals(?foo barbazbat?); Again, \s could save spaces from stripping. From brian.goetz at oracle.com Tue Oct 1 01:37:01 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 30 Sep 2019 21:37:01 -0400 Subject: JDK-8227870 - Escape Sequences For Line Continuation and White Space (Preview) In-Reply-To: <9B49D074-D44F-4738-AF69-6844CF90EBDC@oracle.com> References: <33968389-E102-4778-8BB8-DDF2D2A30416@oracle.com> <9B49D074-D44F-4738-AF69-6844CF90EBDC@oracle.com> Message-ID: This seems to cross the line between ?new escape sequence? and ?bespoke string literal language..." > On Sep 30, 2019, at 9:30 PM, John Rose wrote: > > On Sep 30, 2019, at 4:45 AM, Jim Laskey wrote: >> >> During the discussion on Text Blocks, several of you stated a need for a line continuation construct. I have since created a CSR to propose the creation of two new escape sequences: \ and \s. >> >> https://bugs.openjdk.java.net/browse/JDK-8227870 >> > > One observation: Some traditional uses of \LT, as in C macros, makefiles, and shell, > line up the \ characters in a single column as a sort of right-hand fence: > > foo bar \ > baz \ > bat > > This can be done only in settings where the spaces before the \ are treated as > ancillary format, not payload characters. We could make a similar rule for multi-line > literals, by saying that unescaped spaces *before* the \LT are also deleted when > the \LT sequence is deleted. > > In other words, the \ at the end of the line is *not* a fence that transforms the > > So: > > var x = ??? > foo bar \ > baz \ > bat \ > ???; > assert x.equals(?foo bar baz bat?); > > The single space before baz and the three spaces before bat are the left-hand > leading spaces, not the ancillary spaces before the \ characters. > > If some of those trailing spaces are desirable, then \s can be used to make > a fence that saves them from stripping. > > var x = ??? > foo bar\s \ > baz \s \ > bat\s \ > ???; > assert x.equals(?foo bar baz bat ?); > > This rule decouples the two functions of \LT in the current proposal: (1) It joins > lines, and (2) it creates a fence which makes previously ancillary spaces into > real payload spaces. These are distinct jobs and should not be conflated. > I think it?s a small but real improvement to separate the jobs, and allow \s > to handle (2) and \LT to handle only (1). > > ? John > > P.S. A variation of the above suggestion, probably less preferable, would delete > spaces both *before* and *after* \LT, leading to this: > > var x = ??? > foo bar \ > baz \ > bat \ > ???; > assert x.equals(?foo barbazbat?); > > Again, \s could save spaces from stripping. > > From john.r.rose at oracle.com Tue Oct 1 01:41:13 2019 From: john.r.rose at oracle.com (John Rose) Date: Mon, 30 Sep 2019 18:41:13 -0700 Subject: JDK-8227870 - Escape Sequences For Line Continuation and White Space (Preview) In-Reply-To: References: <33968389-E102-4778-8BB8-DDF2D2A30416@oracle.com> <9B49D074-D44F-4738-AF69-6844CF90EBDC@oracle.com> Message-ID: On Sep 30, 2019, at 6:37 PM, Brian Goetz wrote: > > This seems to cross the line between ?new escape sequence? and ?bespoke string literal language..." Nope, I disagree. It just applies the current concept ?ancillary trailing space? (which did not cross that line) to the spaces before \ at the end of the line. When you think about the detailed mechanics of ancillary spaces before \LT, you surely note that some tricky processing is going on, since they are stripped via a different rule than ancillary spaces before LT. Maybe that makes the feature feel weighty to you. But users won?t care a bit. They will just know that unescaped spaces at the end of the line are ancillary whether or not \ is present between them and the LT. That makes the overall user model simpler, not more complex. From chris.hegarty at oracle.com Tue Oct 1 10:56:55 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Tue, 1 Oct 2019 11:56:55 +0100 Subject: Draft Object Serialization Specification for records Message-ID: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> Please find a link to the draft serialization spec for records: https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.03.html This spec will be updated to reflect the upcoming core reflection changes for RecordComponent. Comments welcome. -Chris. From brian.goetz at oracle.com Tue Oct 1 20:20:17 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 1 Oct 2019 16:20:17 -0400 Subject: Exploring inference for sealed types In-Reply-To: References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> Message-ID: <5bdb7e2b-8fb3-c7ad-c33a-f8ce65d72aba@oracle.com> Having received no further feedback, I'm inclined to proceed on Baseline+A+B. On 9/24/2019 2:34 PM, Brian Goetz wrote: > > So my suggestion is to start with Baseline + (A | A&B), limiting > inference to permits clauses, and see if that is enough. From forax at univ-mlv.fr Tue Oct 1 20:37:02 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 1 Oct 2019 22:37:02 +0200 (CEST) Subject: Exploring inference for sealed types In-Reply-To: <5bdb7e2b-8fb3-c7ad-c33a-f8ce65d72aba@oracle.com> References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> <5bdb7e2b-8fb3-c7ad-c33a-f8ce65d72aba@oracle.com> Message-ID: <1945396188.1074721.1569962222877.JavaMail.zimbra@u-pem.fr> I believe we should allow ourselves to add C in the future, so Baseline + A + B + any subtypes of a sealed types using the permit clause implicitly should be explicitly declared final, sealed or non-sealed. R?mi ----- Mail original ----- > De: "Brian Goetz" > ?: "Gavin Bierman" , "amber-spec-experts" > Envoy?: Mardi 1 Octobre 2019 22:20:17 > Objet: Re: Exploring inference for sealed types > Having received no further feedback, I'm inclined to proceed on > Baseline+A+B. > > On 9/24/2019 2:34 PM, Brian Goetz wrote: >> >> So my suggestion is to start with Baseline + (A | A&B), limiting > > inference to permits clauses, and see if that is enough. From brian.goetz at oracle.com Tue Oct 1 21:02:50 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 1 Oct 2019 17:02:50 -0400 Subject: Exploring inference for sealed types In-Reply-To: <1945396188.1074721.1569962222877.JavaMail.zimbra@u-pem.fr> References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> <5bdb7e2b-8fb3-c7ad-c33a-f8ce65d72aba@oracle.com> <1945396188.1074721.1569962222877.JavaMail.zimbra@u-pem.fr> Message-ID: <155ae638-1a24-4f5b-a424-518a2ad608a9@oracle.com> Baseline says that "you have to be explicit", so omitting one of the three finality modifiers would be an error.? That leaves room for giving meaning to the absence of modifiers later (either implicitly final, or inferred.) On 10/1/2019 4:37 PM, Remi Forax wrote: > I believe we should allow ourselves to add C in the future, > so Baseline + A + B + any subtypes of a sealed types using the permit clause implicitly should be explicitly declared final, sealed or non-sealed. > > R?mi > > ----- Mail original ----- >> De: "Brian Goetz" >> ?: "Gavin Bierman" , "amber-spec-experts" >> Envoy?: Mardi 1 Octobre 2019 22:20:17 >> Objet: Re: Exploring inference for sealed types >> Having received no further feedback, I'm inclined to proceed on >> Baseline+A+B. >> >> On 9/24/2019 2:34 PM, Brian Goetz wrote: >>> So my suggestion is to start with Baseline + (A | A&B), limiting >>> inference to permits clauses, and see if that is enough. From forax at univ-mlv.fr Tue Oct 1 21:09:01 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Tue, 1 Oct 2019 23:09:01 +0200 (CEST) Subject: Exploring inference for sealed types In-Reply-To: <155ae638-1a24-4f5b-a424-518a2ad608a9@oracle.com> References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> <5bdb7e2b-8fb3-c7ad-c33a-f8ce65d72aba@oracle.com> <1945396188.1074721.1569962222877.JavaMail.zimbra@u-pem.fr> <155ae638-1a24-4f5b-a424-518a2ad608a9@oracle.com> Message-ID: <1706706466.1080783.1569964141835.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Remi Forax" > Cc: "Gavin Bierman" , "amber-spec-experts" > Envoy?: Mardi 1 Octobre 2019 23:02:50 > Objet: Re: Exploring inference for sealed types > Baseline says that "you have to be explicit", so omitting one of the three finality modifiers would be an error.? ok, > That leaves room for giving meaning to the absence of modifiers later (either implicitly final, or inferred.) yes ! so +1 for me. R?mi > > On 10/1/2019 4:37 PM, Remi Forax wrote: >> I believe we should allow ourselves to add C in the future, >> so Baseline + A + B + any subtypes of a sealed types using the permit clause >> implicitly should be explicitly declared final, sealed or non-sealed. >> >> R?mi >> >> ----- Mail original ----- >>> De: "Brian Goetz" >>> ?: "Gavin Bierman" , "amber-spec-experts" >>> >>> Envoy?: Mardi 1 Octobre 2019 22:20:17 >>> Objet: Re: Exploring inference for sealed types >>> Having received no further feedback, I'm inclined to proceed on >>> Baseline+A+B. >>> >>> On 9/24/2019 2:34 PM, Brian Goetz wrote: >>>> So my suggestion is to start with Baseline + (A | A&B), limiting > >>> inference to permits clauses, and see if that is enough. From john.r.rose at oracle.com Tue Oct 1 23:26:51 2019 From: john.r.rose at oracle.com (John Rose) Date: Tue, 1 Oct 2019 16:26:51 -0700 Subject: Exploring inference for sealed types In-Reply-To: <1706706466.1080783.1569964141835.JavaMail.zimbra@u-pem.fr> References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> <5bdb7e2b-8fb3-c7ad-c33a-f8ce65d72aba@oracle.com> <1945396188.1074721.1569962222877.JavaMail.zimbra@u-pem.fr> <155ae638-1a24-4f5b-a424-518a2ad608a9@oracle.com> <1706706466.1080783.1569964141835.JavaMail.zimbra@u-pem.fr> Message-ID: Yeah, +1 for me too. It?s a good start, and maybe a fine finish. I?ll comment directly to Gavin?s message on the extra inference beyond base+A+B. > On Oct 1, 2019, at 2:09 PM, forax at univ-mlv.fr wrote: > > ----- Mail original ----- >> De: "Brian Goetz" >> ?: "Remi Forax" >> Cc: "Gavin Bierman" , "amber-spec-experts" >> Envoy?: Mardi 1 Octobre 2019 23:02:50 >> Objet: Re: Exploring inference for sealed types > >> Baseline says that "you have to be explicit", so omitting one of the three finality modifiers would be an error. > > ok, > >> That leaves room for giving meaning to the absence of modifiers later (either implicitly final, or inferred.) > > yes ! > > so +1 for me. > > R?mi > >> >> On 10/1/2019 4:37 PM, Remi Forax wrote: >>> I believe we should allow ourselves to add C in the future, >>> so Baseline + A + B + any subtypes of a sealed types using the permit clause >>> implicitly should be explicitly declared final, sealed or non-sealed. >>> >>> R?mi >>> >>> ----- Mail original ----- >>>> De: "Brian Goetz" >>>> ?: "Gavin Bierman" , "amber-spec-experts" >>>> >>>> Envoy?: Mardi 1 Octobre 2019 22:20:17 >>>> Objet: Re: Exploring inference for sealed types >>>> Having received no further feedback, I'm inclined to proceed on >>>> Baseline+A+B. >>>> >>>> On 9/24/2019 2:34 PM, Brian Goetz wrote: >>>>> So my suggestion is to start with Baseline + (A | A&B), limiting >>>>> inference to permits clauses, and see if that is enough. From john.r.rose at oracle.com Wed Oct 2 00:05:03 2019 From: john.r.rose at oracle.com (John Rose) Date: Tue, 1 Oct 2019 17:05:03 -0700 Subject: Exploring inference for sealed types In-Reply-To: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> Message-ID: <39468FB0-111C-44AE-8E52-D0BA2548EBD9@oracle.com> On Sep 23, 2019, at 9:04 AM, Gavin Bierman wrote: > > ... > But there are wrinkles with this design. > > 1. Obviously we will rule out the explicit declaration of an empty `permits` > clause, but what if we _infer_ one? To be concrete where we have the > compilation unit: > > ``` > sealed class Foo { } > //EOF > ``` > > What's the right thing here? Is this an compile-time error? A `sealed` class > with an empty `permits` clause is morally `final`, so should we infer the > class to be `final`? Or do we need to keep the two - `final` and > `sealed`-with-empty-`permits`) and make sure we treat them identically? From a VM point of view I?d rather not have two configurations that both amount of ?final? (classic final + sealed-with-empty-permits). Adding unused degrees of freedom adds places for bugs to hide. From a source point of view, when the sealed class has no subs, it seems just fine for javac to report an error requiring a bit of ceremony to change ?sealed? to ?final?. The end product is more readable (less ambiguous), so the adjustment is a legitimate thing to require. > 2. Consider the following: > > ``` > class Outer { > sealed class SuperSealed {} > > sealed interface SealedI {} > > class SubFinal1 extends SuperSealed {} > > class SubFinal2 implements SealedI {} > > non-sealed SubNonSealed extends SuperSealed implements SealedI {} > > class WhatAboutMe extends SubNonSealed implements SealedI {} //maybe also non-sealed NonSealedI extends SealedI {} interface WhatAboutMeToo extends NonSealedI, SuperSealed {} > } > ``` > > The issue is around class WhatAboutMe. It redundantly implements SealedI. But > with the cascading behavior this is significant. *With* the `implements` clause > we infer that WhatAboutMe should be `final`. *Without* it we would not. > > As is common with other inference systems, our inference may not be invariant > under semantically equivalent declarations. Is that going to be too > confusing for users? Yes, it will be confusing. It is probably one of the reasons we are shying away from this level of inferencing: It?s got at least one surprise in it. A standard answer to surprises is to outlaw them, on the grounds that if they are surprising they might as well be declared illegal ambiguities. So if the supers of an unmarked type are a mix of open and sealed, the inferencer doesn?t pick a favorite; rather, it requires the user to write an explicit (non-inferred) choice. So WhatAboutMe would be open without the implements clause, and *in error* with the implements clause, on the grounds that its two supers can?t agree about their effect on inference. Since only local classes affect such inference, the error check can look for a mix of supers (two implements, or a super-class and an implement) which were (a) local and (b) differing in their open-ness. In the case of WhatAboutMe, an extra feature is that it redundantly implements SealedI. I don?t think the error check needs to care about that feature; it only needs to look a mix of sealed and non-sealed supers *among the supers defined in the same compilation unit*. The compiler will complain, and the user will grumble a bit and add ?sealed? (or ?final?) or ?non-sealed? to the type with the funny mix of supers. As before, it?s worth it since it improves readability in a place that would otherwise be doubtful. > 3. This cascading inference puts strain on the compiler. It works by analyzing > which types extend/implement the `sealed` type in question. Whilst such > hierarchies are probably going to be small, one could imagine people > exploiting this inference feature and building extensive and complicated > sealed hierarchies within a single compilation unit. Do we want to commit > compilers to navigating these graphs? Would we be encouraging people to defining > auxiliary classes when we have been recommending *not* to do so? Easy for me to say as a VM guy, but compile time is cheap. Also, source files are usually pretty small. If a user puts 1000s of types in a source file and gets a slow compilation, it?s obvious what to do. > Thoughts welcome! > Gavin > > SPEC DETAILS > ------------ > > To deal with modifiers; first for classes: > > --- > > If a class _C_ extends a `sealed` class ([8.1.4]) that is declared in the same > compilation unit ([7.3]), or implements a `sealed` interface ([9.1.1.3]) that > is declared in the same compilation unit, one of the following applies: > > - The class is explicitly declared `final` or `sealed`. > > - The class is explicitly declared `non-sealed`, meaning that there are no > restrictions on the subclasses of _C_. > > - The class is not declared `final`, `sealed`, nor `non-sealed`. In this case, > if _C_ is the direct superclass ([8.1.4]) of another class declared in the > same compilation unit, then class _C_ is implicitly declared `sealed`; > otherwise class _C_ is implicitly declared `final`. Add an exception: - Nevertheless, if such an implicitly modified _C_extends a class or implements an interface defined in the same compilation unit, and that class or interface is implicitly or explicitly marked non-sealed, then a compile-time error occurs. > > Otherwise, if a class _C_ extends a `sealed` class or implements a `sealed` > interface, one of the following applies: > > - The class is explicitly declared `final` or `sealed`. > > - The class is explicitly declared `non-sealed`, meaning that there are no > restrictions on the subclasses of _C_. > > - The class is not declared `final`, `sealed`, nor `non-sealed`, and a > compile-time error occurs. > > --- > > And for interfaces: > > --- > > If an interface _I_ extends a `sealed` interface ([9.1.3]) that is declared in > the same compilation unit ([7.3]), one of the following applies: > > - The interface _I_ is explicitly declared `sealed`. > > - The interface _I_ is explicitly declared `non-sealed`, meaning that there are > no restrictions on the subtypes of _I_. > > - The interface _I_ is not declared `sealed` or `non-sealed`. In this case, if > _I_ is the superinterface ([8.1.5], [9.1.3]) of another class or interface > declared in the same compilation unit, then interface _I_ is implicitly > declared `sealed`; otherwise a compile-time error occurs. Add an exception: - Nevertheless, if such an implicitly modified _I_extends an interface defined in the same compilation unit, and that interface is implicitly or explicitly marked non-sealed, then a compile-time error occurs. > --- > > To deal with `permits` clauses; first for classes: > > --- > > A `sealed` class _C_ without an explicitly declared `permits` > clause, has an implicitly declared `permits` clause that lists as permitted > subclasses all the classes in the same compilation unit ([7.3]) as _C_ that > declare _C_ as their direct superclass. Add: There must be at least one such class, or a compile-time error occurs. > > --- > > and for interfaces: > > --- > > If a `sealed` interface _I_ does not have an explicit `permits` clause, then > it has an implicitly declared `permits` clause that lists as permitted > subtypes all the classes and interfaces in the same compilation unit ([7.3]) > as _I_ that declare _I_ as their direct superinterface. > Add: There must be at least one such class or interface, or a compile-time error occurs. > --- From peter.levart at gmail.com Wed Oct 2 13:27:38 2019 From: peter.levart at gmail.com (Peter Levart) Date: Wed, 2 Oct 2019 15:27:38 +0200 Subject: instance initializer In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <129906317.2061938.1567191204608.JavaMail.zimbra@u-pem.fr> <3AD49B61-3249-4F17-A123-5CA8F74224B6@oracle.com> <207864159.802202.1567512142874.JavaMail.zimbra@u-pem.fr> <894af760-fd0d-42c6-ca41-e472b6b06f91@oracle.com> <584049515.2091404.1567721679566.JavaMail.zimbra@u-pem.fr> <49a00616-84e4-2a86-de53-1aac5881f7d9@oracle.com> <898768A6-C90A-477B-9468-4DA7C71D1381@oracle.com> Message-ID: Hi, On 9/6/19 2:54 AM, Brian Goetz wrote: > In that case, what we would see is that on exit, neither i nor j were > either DA or DU, and we would issue a compiler error.? For each field, > there are three possibilities: > > ?- The field is DU on all paths out of the ctor; we initialize it from > the corresponding parameter. > ?- The field is DA on all paths out of the ctor; we do nothing. > ?- The field is neither DU nor DA on some path out of the ctor; error. > > We could extend this analysis to the init block, where if its either > of the first two cases, we feed that information back into the ctor > analysis, and always error in the third case -- the real question is > whether its worth the bother. Isn't similar thing already in place for final fields? They have to be DA. Granted this implementation would have to be tweaked because generated code would depend on the outcome of the analysis. Remi's concern that the analysis would have to work on user code + generated code is perhaps unfounded. The analysis would have to work on user code only and the outcome would then be used to generate the automatic code. I think John is proposing a runtime workarround: user code playing with constructor parameters (locals) before assigning them to the fields. In this case all fields would be guaranteed DA at the end. But that doesn't account for instance initializer block(s) as they don't have the constructor parameters in scope. Regards, Peter > > > On 9/5/2019 8:43 PM, John Rose wrote: >> On Sep 5, 2019, at 4:47 PM, Vicente Romero >> wrote: >>> right I was thinking about the case: >>> >>> record R(int i, int j) { >>> ???? public R {? // compact constructor >>> ???????? if (i < 0) { >>> ???????????? this.i = -i; >>> ???????? } else { >>> ???????????? this.j = j; >>> ???????? } >>> ???? } >>> } >> Correct me if I?m wrong, but we can cover cases like this by >> assigning to the component parameters, and let the fields get written >> automatically: >> >> record R(int i, int j) { >> ???? public R {? // compact constructor >> ???????? if (i < 0) { >> ???????????? i = -i;? // not this.i >> ???????? } else { >> ???????????? j = i+j;? // not this.j >> ???????? } >> ???? } >> } >> > From peter.levart at gmail.com Wed Oct 2 20:43:16 2019 From: peter.levart at gmail.com (Peter Levart) Date: Wed, 2 Oct 2019 22:43:16 +0200 Subject: Exploring inference for sealed types In-Reply-To: References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> Message-ID: Hi, On 9/24/19 8:34 PM, Brian Goetz wrote: > So one sensible increment atop the baseline is: (A) if a top-level > type is explicitly declared sealed, and has no permits clause, we can > infer the permits clause from the subtypes in the compilation unit (or > more narrowly, the _nested_ subtypes).? This is simpler than the full > scheme outlined, while addressing the biggest case that concerns me -- > the high-fanout case. > > The above scheme could be incrementally extended to (B) any class > explicitly marked `sealed` -- if you say sealed and leave off > `permits`, the permits list is inferred from the current compilation > unit.? This seems defensible. Is compilation unit really the right choice to base inference on? For example, a program may be composed of several modules compiled all at once in a single compilation unit (javac supports that). This same program may be compiled with a build system such as Maven, which compiles each module separately as its own compilation unit. Would we really want the semantics of a program (or successful compilation thereoff) depend on the choice of the build tool? What about using (module, compilation unit) as the base to perform inference within? I understand that compiler may only infer things within a compilation unit and module is usually compiled as a whole in one compilation unit (possibly together with other modules). Regards, Peter From alex.buckley at oracle.com Wed Oct 2 21:08:37 2019 From: alex.buckley at oracle.com (Alex Buckley) Date: Wed, 2 Oct 2019 14:08:37 -0700 Subject: Exploring inference for sealed types In-Reply-To: References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> Message-ID: <9ecd0f14-d6d5-0398-74c2-4bbd47f81976@oracle.com> You speak of "compilation unit" as if it means the scope of work performed by javac and Maven. ("compiles each module separately as its own compilation unit") That's not the meaning. The meaning is as given in https://docs.oracle.com/javase/specs/jls/se13/html/jls-7.html#jls-7.3 On 10/2/2019 1:43 PM, Peter Levart wrote: > Is compilation unit really the right choice to base inference on? > > For example, a program may be composed of several modules compiled all > at once in a single compilation unit (javac supports that). This same > program may be compiled with a build system such as Maven, which > compiles each module separately as its own compilation unit. Would we > really want the semantics of a program (or successful compilation > thereoff) depend on the choice of the build tool? > > What about using (module, compilation unit) as the base to perform > inference within? I understand that compiler may only infer things > within a compilation unit and module is usually compiled as a whole in > one compilation unit (possibly together with other modules). > > Regards, Peter > From peter.levart at gmail.com Fri Oct 4 16:01:50 2019 From: peter.levart at gmail.com (Peter Levart) Date: Fri, 4 Oct 2019 18:01:50 +0200 Subject: Exploring inference for sealed types In-Reply-To: <9ecd0f14-d6d5-0398-74c2-4bbd47f81976@oracle.com> References: <814E99F0-4DAE-4FFE-A045-CC454ADB5829@oracle.com> <9ecd0f14-d6d5-0398-74c2-4bbd47f81976@oracle.com> Message-ID: <731c1315-6a59-22fa-ed80-b9f135c13e38@gmail.com> Of course! My bad. Compilation unit which usually maps to .java file when compiling files... That's perfectly sensible as a scope to define inference within. Regards, Peter On 10/2/19 11:08 PM, Alex Buckley wrote: > You speak of "compilation unit" as if it means the scope of work > performed by javac and Maven. ("compiles each module separately as its > own compilation unit")? That's not the meaning. The meaning is as > given in > https://docs.oracle.com/javase/specs/jls/se13/html/jls-7.html#jls-7.3 > > On 10/2/2019 1:43 PM, Peter Levart wrote: >> Is compilation unit really the right choice to base inference on? >> >> For example, a program may be composed of several modules compiled >> all at once in a single compilation unit (javac supports that). This >> same program may be compiled with a build system such as Maven, which >> compiles each module separately as its own compilation unit. Would we >> really want the semantics of a program (or successful compilation >> thereoff) depend on the choice of the build tool? >> >> What about using (module, compilation unit) as the base to perform >> inference within? I understand that compiler may only infer things >> within a compilation unit and module is usually compiled as a whole >> in one compilation unit (possibly together with other modules). >> >> Regards, Peter >> From forax at univ-mlv.fr Fri Oct 4 19:52:24 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 4 Oct 2019 21:52:24 +0200 (CEST) Subject: Record bytecode format not described in JEP 359 Message-ID: <1311706012.2712061.1570218744332.JavaMail.zimbra@u-pem.fr> Hi everyone, i'm implementing the support of record (and sealed types) in ASM as an experimental (preview if you prefer) feature of the future ASM8. The JEP 359 [1], doesn't include the bytecode format of the Record attribute, is there a reason ? R?mi [1] https://openjdk.java.net/jeps/359 From brian.goetz at oracle.com Fri Oct 4 20:29:35 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 4 Oct 2019 16:29:35 -0400 Subject: Record bytecode format not described in JEP 359 In-Reply-To: <1311706012.2712061.1570218744332.JavaMail.zimbra@u-pem.fr> References: <1311706012.2712061.1570218744332.JavaMail.zimbra@u-pem.fr> Message-ID: <1b63514e-cf2b-1079-30ed-b5c3e30309d7@oracle.com> The JEP issue has a sub-task, JVMS for records, which is where the spec would be attached.? There is currently no draft there, but we'll post one soon. On 10/4/2019 3:52 PM, Remi Forax wrote: > Hi everyone, > i'm implementing the support of record (and sealed types) in ASM as an experimental (preview if you prefer) feature of the future ASM8. > > The JEP 359 [1], doesn't include the bytecode format of the Record attribute, is there a reason ? > > R?mi > [1] https://openjdk.java.net/jeps/359 From vicente.romero at oracle.com Fri Oct 4 21:33:27 2019 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 4 Oct 2019 17:33:27 -0400 Subject: Record bytecode format not described in JEP 359 In-Reply-To: <1311706012.2712061.1570218744332.JavaMail.zimbra@u-pem.fr> References: <1311706012.2712061.1570218744332.JavaMail.zimbra@u-pem.fr> Message-ID: <80804531-8d5f-330d-8698-58d959472e59@oracle.com> Hi Remi, In the meantime you should be able to access the current definition of the Record attribute at [1]. Thanks, Vicente [1] https://bugs.openjdk.java.net/browse/JDK-8225058 On 10/4/19 3:52 PM, Remi Forax wrote: > Hi everyone, > i'm implementing the support of record (and sealed types) in ASM as an experimental (preview if you prefer) feature of the future ASM8. > > The JEP 359 [1], doesn't include the bytecode format of the Record attribute, is there a reason ? > > R?mi > [1] https://openjdk.java.net/jeps/359 From forax at univ-mlv.fr Fri Oct 4 21:44:11 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Fri, 4 Oct 2019 23:44:11 +0200 (CEST) Subject: Record bytecode format not described in JEP 359 In-Reply-To: <80804531-8d5f-330d-8698-58d959472e59@oracle.com> References: <1311706012.2712061.1570218744332.JavaMail.zimbra@u-pem.fr> <80804531-8d5f-330d-8698-58d959472e59@oracle.com> Message-ID: <1841557669.2719591.1570225451495.JavaMail.zimbra@u-pem.fr> Thank Vicente, I suppose you also have visible and invisible annotations as attribute too ? R?mi ----- Mail original ----- > De: "Vicente Romero" > ?: "Remi Forax" , "amber-spec-experts" > Envoy?: Vendredi 4 Octobre 2019 23:33:27 > Objet: Re: Record bytecode format not described in JEP 359 > Hi Remi, > > In the meantime you should be able to access the current definition of > the Record attribute at [1]. > > Thanks, > Vicente > > [1] https://bugs.openjdk.java.net/browse/JDK-8225058 > > On 10/4/19 3:52 PM, Remi Forax wrote: >> Hi everyone, >> i'm implementing the support of record (and sealed types) in ASM as an >> experimental (preview if you prefer) feature of the future ASM8. >> >> The JEP 359 [1], doesn't include the bytecode format of the Record attribute, is >> there a reason ? >> >> R?mi > > [1] https://openjdk.java.net/jeps/359 From peter.levart at gmail.com Sun Oct 6 14:48:16 2019 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 06 Oct 2019 16:48:16 +0200 Subject: Draft JLS spec for records - local types In-Reply-To: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: <2452487.ezX9TyzB4F@cube> On Friday, August 23, 2019 11:25:05 PM CEST Gavin Bierman wrote: > A draft language spec for records is available at: > > http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-> jls.html Hi Gavin, When reading the spec, the following caught my attention: """A nested record type is implicitly static. It is permitted for the declaration of a nested record type to redundantly specify the static modifier. This implies that it is impossible to declare a record type in the body of an inner class (8.1.3), because an inner class cannot have static members except for constant variables. """ So in this respect, record type is similar to enum type which is also implicitly static. Although the JLS does not mention explicitly (or at least I can't find it), enum types are not allowed as local types (declared inside methods, constructors or initializers). For example: public class Test { static void method() { enum E {A, B} // Error: enum types must not be local } } Are record types the same? I never quite understood why: - it is not possible to declare static local classes (enum types included) - declare static members in inner classes Sometimes you would just want a simple static data holder with local scope (for example an intermediate data element in some Stream stage). And records would be perfect for that with their concise syntax. But if there is some deeper reason why static members are not allowed in "local" context(s) then perhaps record types should behave the same as enum types. Regards, Peter From brian.goetz at oracle.com Sun Oct 6 15:06:14 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 6 Oct 2019 11:06:14 -0400 Subject: Draft JLS spec for records - local types In-Reply-To: <2452487.ezX9TyzB4F@cube> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <2452487.ezX9TyzB4F@cube> Message-ID: <4CA095B6-C83D-4F6A-BC09-121469FF5C21@oracle.com> > When reading the spec, the following caught my attention: > > """A nested record type is implicitly static. It is permitted for the > declaration of a nested record type to redundantly specify the static > modifier. > > This implies that it is impossible to declare a record type in the body of > an inner class (8.1.3), because an inner class cannot have static members > except for constant variables. Sharp eye! Yes, this is sad. There are three ways to go: - Don?t make records implicitly static. - Allow static members in inner classes. - Don?t allow records in inner classes, at least for now, and do one of the others later. I don?t like the first one; inner records violate the spirit of records, which is their entire representation, API, and behavior is derived from their state descriptor. An inner record would have a hidden extra component, and this would raise uncomfortable questions like ?how does it play into the equally calculation.? Better to say records are what they look like, which makes them implicitly static. In the long run, I would like to bust the restriction on inner classes not having static members. (And similarly, open the door to local enums, local interfaces, etc.) These fall into the category we?ve been calling ?smoother scoping?, which is eliminating some of the ad-hoc nest-x-in-y restrictions. It seems the sensible strategy for now is accept the restriction, and fix it as by busting the restriction on inner classes when we can. Its possible we can relax this for records now and general static members later. > So in this respect, record type is similar to enum type which is also > implicitly static. Record is similar to enum in many, many ways? > Although the JLS does not mention explicitly (or at least I can't find it), > enum types are not allowed as local types (declared inside methods, > constructors or initializers). For example: Local records should be allowed; we should probably allow local enums at the same time. From forax at univ-mlv.fr Sun Oct 6 15:29:44 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 6 Oct 2019 17:29:44 +0200 (CEST) Subject: Draft JLS spec for records - local types In-Reply-To: <4CA095B6-C83D-4F6A-BC09-121469FF5C21@oracle.com> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <2452487.ezX9TyzB4F@cube> <4CA095B6-C83D-4F6A-BC09-121469FF5C21@oracle.com> Message-ID: <1426346927.18053.1570375784643.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Peter Levart" > Cc: "amber-spec-experts" > Envoy?: Dimanche 6 Octobre 2019 17:06:14 > Objet: Re: Draft JLS spec for records - local types >> When reading the spec, the following caught my attention: >> >> """A nested record type is implicitly static. It is permitted for the >> declaration of a nested record type to redundantly specify the static >> modifier. >> >> This implies that it is impossible to declare a record type in the body of >> an inner class (8.1.3), because an inner class cannot have static members >> except for constant variables. > > Sharp eye! > > Yes, this is sad. There are three ways to go: > > - Don?t make records implicitly static. > - Allow static members in inner classes. > - Don?t allow records in inner classes, at least for now, and do one of the > others later. > > I don?t like the first one; inner records violate the spirit of records, which > is their entire representation, API, and behavior is derived from their state > descriptor. An inner record would have a hidden extra component, and this > would raise uncomfortable questions like ?how does it play into the equally > calculation.? Better to say records are what they look like, which makes them > implicitly static. yes, an implicit extra component also doesn't play well with the pattern matching extraction. R?mi From peter.levart at gmail.com Sun Oct 6 16:13:21 2019 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 06 Oct 2019 18:13:21 +0200 Subject: instance initializer In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: <5571324.9zj6BMyFhJ@cube> Hi, Just thinking loud here... On Wednesday, October 2, 2019 3:27:38 PM CEST Peter Levart wrote: > Hi, > > On 9/6/19 2:54 AM, Brian Goetz wrote: > > In that case, what we would see is that on exit, neither i nor j were > > either DA or DU, and we would issue a compiler error. For each field, > > there are three possibilities: > > > > - The field is DU on all paths out of the ctor; we initialize it from > > the corresponding parameter. > > - The field is DA on all paths out of the ctor; we do nothing. > > - The field is neither DU nor DA on some path out of the ctor; error. > > > > We could extend this analysis to the init block, where if its either > > of the first two cases, we feed that information back into the ctor > > analysis, and always error in the third case -- the real question is > > whether its worth the bother. > > Isn't similar thing already in place for final fields? They have to be > DA. Granted this implementation would have to be tweaked because > generated code would depend on the outcome of the analysis. Remi's > concern that the analysis would have to work on user code + generated > code is perhaps unfounded. The analysis would have to work on user code > only and the outcome would then be used to generate the automatic code. > > I think John is proposing a runtime workarround: user code playing with > constructor parameters (locals) before assigning them to the fields. In > this case all fields would be guaranteed DA at the end. But that doesn't > account for instance initializer block(s) as they don't have the > constructor parameters in scope. > Instance initializers don't play well in records. Why? They don't play well with the notion of canonical constructor. Records mandate two things among others: - formal parameters of a mandatory canonical constructor - instance fields You can't skip a field and you can't add one. You can't skip a parameter of the canonical constructor and you can't add one. Both of them are always in sync with the declared record components. What is the purpose of instance initializer? (Partly) initializing the state of the object. So to have any meaning (besides side effects that do not pertain to instance state), instance initializer must set at least one instance field. If it does set it, then what is the purpose of a mandatory canonical constructor parameter that relates to that field? It must be ignored. Not very sensible. So I was thinking about some constraints that would still allow everything except insensible things: - do allow to override implicit canonical constructor with classical constructor having exact number, types and order of parameters as the declared record components. Rules in such constructor are unchanged. - do allow to override implicit canonical constructor with compact constructor, but don't allow access to instance fields in the compact constructor. - allow other constructors besides canonical constructor, but don't allow access to instance fields inside them from code where the record instance is not "Definitely Initialized". Make it compile time error if record instance is not "Definitely Initialized" in all normal exit paths from the constructor. What does it mean for record instance to be "Definitely Initialized" or DI? Record instance is DI if all its instance fields are DA. How do we achieve DI in all normal exit paths from the record constructors if access to fields inside constructor is not allowed until the instance is DI? In classical canonical constructor, this is achieved classically. In compact canonical constructor, this is achieved by automatic assignment of all constructor parameters to instance fields at all normal exit paths from the constructor. In other constructors this is achieved by chaining to some other (possibly canonical) constructor, i.e. calling: this(....); In these scheme, canonical constructor also acts as instance initializer, since it is always called from other constructors. Classical instance initializer is therefore not needed any more and could be prohibited in record types. What do you think? Regards, Peter From brian.goetz at oracle.com Sun Oct 6 16:21:45 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 6 Oct 2019 12:21:45 -0400 Subject: instance initializer In-Reply-To: <5571324.9zj6BMyFhJ@cube> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <5571324.9zj6BMyFhJ@cube> Message-ID: <757b649e-037d-1705-be2d-272717b5d431@oracle.com> > In these scheme, canonical constructor also acts as instance initializer, > since it is always called from other constructors. Classical instance > initializer is therefore not needed any more and could be prohibited in record > types. > I would agree that instance initializers in records are mostly useless, and keeping them around adds some complexity.? Any work that can be done in an II could also be done in a compact ctor with about the same number of keystrokes: ??? { ++instanceCount; } vs ?? Foo { ++instanceCount; } The argument for keeping them is to minimize the number of gratuitous differences between records and classes.? But, "it is a compile-time error for a record class to have an instance initializer" is a pretty simple spec change... and probably no one will notice. From peter.levart at gmail.com Sun Oct 6 16:51:41 2019 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 06 Oct 2019 18:51:41 +0200 Subject: instance initializer In-Reply-To: <757b649e-037d-1705-be2d-272717b5d431@oracle.com> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <5571324.9zj6BMyFhJ@cube> <757b649e-037d-1705-be2d-272717b5d431@oracle.com> Message-ID: <1830756.zWCvX6glAt@cube> On Sunday, October 6, 2019 6:21:45 PM CEST Brian Goetz wrote: > > In these scheme, canonical constructor also acts as instance initializer, > > since it is always called from other constructors. Classical instance > > initializer is therefore not needed any more and could be prohibited in > > record types. > > I would agree that instance initializers in records are mostly useless, > and keeping them around adds some complexity. Any work that can be done > in an II could also be done in a compact ctor with about the same number > of keystrokes: > > { ++instanceCount; } > > vs > > Foo { ++instanceCount; } > > The argument for keeping them is to minimize the number of gratuitous > differences between records and classes. But, "it is a compile-time > error for a record class to have an instance initializer" is a pretty > simple spec change... and probably no one will notice. I know that making special rules in record constructors (about being able to access instance fields) is also increasing the number of gratuitous differences between records and classes, but in order to ban instance initializers, there has to be a an alternative way to specify initializing code that is always executed. Perhaps it is enough just to suggest users to put such code into canonical constructor and always call that constructor from other constructors as opposed to forcing them to do that with language constraints. Regards, Peter From peter.levart at gmail.com Sun Oct 6 21:23:20 2019 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 06 Oct 2019 23:23:20 +0200 Subject: Draft Object Serialization Specification for records - serialVersionUID In-Reply-To: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> Message-ID: <1671466.UgekT7RP32@cube> Hi Chris, On Tuesday, October 1, 2019 12:56:55 PM CEST Chris Hegarty wrote: > Please find a link to the draft serialization spec for records: > > https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.03.ht > ml > > This spec will be updated to reflect the upcoming core reflection > changes for RecordComponent. > > Comments welcome. > > -Chris. Above draft says: """Any serialPersistentFields or serialVersionUID field declarations are also ignored -- all record classes have a fixed serialVersionUID of 0L. """ So how does this work with migration plan? When a record-like class C with serialVersionUID != 0 is migrated to be a record, the stream produced with class C can not be read by a program where C is a record. Or is the value of serialVersionUID in the stream ignored when reading the stream into a record? In that case writing class C -> reading record C is supported, but what about writing record C -> reading class C ? If you still want to support migration, then perhaps the default serialVersionUID of records could be 0L always, but serialVersionUID field would still be considered when this default needs to be overridden. So for types that are records from day 1, users don't have to bother with serialVersionUID fields, but if a type is migrated from class to record, this can still be supported. What do you think? Regards, Peter From peter.levart at gmail.com Sun Oct 6 21:38:42 2019 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 06 Oct 2019 23:38:42 +0200 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> Message-ID: <9756631.sDmPtFT6pA@cube> Hi Chris, On Tuesday, October 1, 2019 12:56:55 PM CEST Chris Hegarty wrote: > Please find a link to the draft serialization spec for records: > > https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.03.ht > ml > > This spec will be updated to reflect the upcoming core reflection > changes for RecordComponent. > > Comments welcome. > > -Chris. Here's a snipped from above draft: """The serialized form of a record object is a sequence of values derived from the final instance fields of the object. The stream format of a record object is the same as that of an ordinary object in the stream. During deserialization, if the local class equivalent of the specified stream class descriptor is a record class, then first the stream fields are read and reconstructed to serve as the record's component values; and second, a record object is created by invoking the record's canonical constructor with the component values as arguments (or the default value for component's type if a component value is absent from the stream). """ I think that if stream values deserialize into a record through its public API (the canonical constructor which can be customized), then record components that are serailzed must also be obtained from a record via its public API (the accessors which can also be customized). I think this is an important aspect which should be spelled out in the specification. So instead of: "The serialized form of a record object is a sequence of values derived from the final instance fields of the object.", the text should go: "The serialized form of a record object is a sequence of values derived from invoking the record component accessors." What do you think? Regards, Peter From peter.levart at gmail.com Sun Oct 6 22:07:26 2019 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 07 Oct 2019 00:07:26 +0200 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: <9756631.sDmPtFT6pA@cube> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> Message-ID: <1995499.Zq99ppJM9V@cube> On Sunday, October 6, 2019 11:38:42 PM CEST Peter Levart wrote: > Hi Chris, > > I think that if stream values deserialize into a record through its public > API (the canonical constructor which can be customized), then record > components that are serailzed must also be obtained from a record via its > public API (the accessors which can also be customized). > ...above discussion also extends to the ObjectOutputStream.writeObject method description that is currently written as: """If the object is a record object, the ObjectStreamClass for the class of the record object is written by recursively calling writeObject. It will appear in the stream only the first time it is referenced. A handle is assigned for the record object. The components of the record object are written to the stream. a. If the record object is serializable or externalizable, the record components are written, as if by invoking the `defaultWriteObject` method. b. If the object is neither serializable or externalizable, the `NotSerializableException` is thrown. The writeObject method then returns. """ So instead of "as if by invoking the `defaultWriteObject`, here you might want to describe how component values are obtained, etc. But I wanted to comment on another thing here: "a. If the record object is serializable or externalizable, ..." How could record be Externalizable? It would have to implement writeExternal(ObjectOutput). No big deal. It would also have to have a public no-arg constructor. No big deal. It would have to implement readExternal(ObjectInput). Wait! How could a record type effectively implement readExternal if all record fields are final? Externalizable and records don't play together well, I think. If a record type wishes to fully customize serialization format it still can designate a serialization proxy (via writeReplace()) which can be an instance of a normal Externalizable class for example. Regards, Peter From forax at univ-mlv.fr Sun Oct 6 22:40:54 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 7 Oct 2019 00:40:54 +0200 (CEST) Subject: sealed interface are abstract and final Message-ID: <1674404116.20115.1570401654754.JavaMail.zimbra@u-pem.fr> Hi all, currently a sealed interface is abstract and final, after having updated ASM to read sealed class/attribute, i try to test it with some sealed types running some bytecode rewriters of mine, and it was ugly. 2 of them flatly don't work on sealed types, because there are written with the assumption that if something final it is a class. Given that a sealed class is not final, why do we need interface to be final ? R?mi From chris.hegarty at oracle.com Mon Oct 7 13:31:56 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Mon, 7 Oct 2019 14:31:56 +0100 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: <1995499.Zq99ppJM9V@cube> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> <1995499.Zq99ppJM9V@cube> Message-ID: Peter, > On 6 Oct 2019, at 23:07, Peter Levart wrote: > > On Sunday, October 6, 2019 11:38:42 PM CEST Peter Levart wrote: >> Hi Chris, >> >> I think that if stream values deserialize into a record through its public >> API (the canonical constructor which can be customized), then record >> components that are serailzed must also be obtained from a record via its >> public API (the accessors which can also be customized). >> > > ...above discussion also extends to the ObjectOutputStream.writeObject method > description that is currently written as: > > """If the object is a record object, the ObjectStreamClass for the class of > the record object is written by recursively calling writeObject. It will > appear in the stream only the first time it is referenced. A handle is > assigned for the record object. > > The components of the record object are written to the stream. > > a. If the record object is serializable or externalizable, the record > components are written, as if by invoking the `defaultWriteObject` > method. > > b. If the object is neither serializable or externalizable, the > `NotSerializableException` is thrown. > > The writeObject method then returns. > """ > > So instead of "as if by invoking the `defaultWriteObject`, here you might want > to describe how component values are obtained, etc. Answered in another email. > But I wanted to comment on another thing here: "a. If the record object is > serializable or externalizable, ..." > > How could record be Externalizable? It would have to implement > writeExternal(ObjectOutput). No big deal. It would also have to have a public > no-arg constructor. No big deal. It would have to implement > readExternal(ObjectInput). Wait! How could a record type effectively implement > readExternal if all record fields are final? Yeah, Externalizable and records are just at odds. The only possible useful externalizable record is a record with no components! Externalizable is a bit of a wart here, but was included for consistency. > Externalizable and records don't play together well, I think. If a record type > wishes to fully customize serialization format it still can designate a > serialization proxy (via writeReplace()) which can be an instance of a normal > Externalizable class for example. > I agree, writeReplace is the correct escape hatch for folk that want something other than the default scheme. The is why it is there. I?m not opposed to dropping support for Externalizable. Is that the suggestion? What should happen if one writes `record R (int x, int y) implements Externalizable { ? }` - a warning or not? maybe an error during serializing / deserializing?? -Chris. From chris.hegarty at oracle.com Mon Oct 7 13:31:51 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Mon, 7 Oct 2019 14:31:51 +0100 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: <9756631.sDmPtFT6pA@cube> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> Message-ID: <1C2C454E-384E-4F28-987E-FA362256C1B5@oracle.com> Peter, > On 6 Oct 2019, at 22:38, Peter Levart wrote: > >> ... > > Here's a snipped from above draft: > > """The serialized form of a record object is a sequence of values derived from > the final instance fields of the object. The stream format of a record object > is the same as that of an ordinary object in the stream. During > deserialization, if the local class equivalent of the specified stream class > descriptor is a record class, then first the stream fields are read and > reconstructed to serve as the record's component values; and second, a record > object is created by invoking the record's canonical constructor with the > component values as arguments (or the default value for component's type if a > component value is absent from the stream). > """ > > I think that if stream values deserialize into a record through its public API > (the canonical constructor which can be customized), then record components > that are serailzed must also be obtained from a record via its public API (the > accessors which can also be customized). > > I think this is an important aspect which should be spelled out in the > specification. So instead of: "The serialized form of a record object is a > sequence of values derived from the final instance fields of the object.", the > text should go: "The serialized form of a record object is a sequence of > values derived from invoking the record component accessors.? You are not wrong. In fact, I had the very same thought ( and the implementation does similar ), but we want to leave room here for deconstructors/extractors. With the wording in the current draft, it will be possible to switch the implementation without the need to update the specification. -Chris. From chris.hegarty at oracle.com Mon Oct 7 13:31:44 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Mon, 7 Oct 2019 14:31:44 +0100 Subject: Draft Object Serialization Specification for records - serialVersionUID In-Reply-To: <1671466.UgekT7RP32@cube> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <1671466.UgekT7RP32@cube> Message-ID: <2B4ED8EB-B064-4FB5-A53B-A6D113EBA83C@oracle.com> Thank you for your feedback Peter. > On 6 Oct 2019, at 22:23, Peter Levart wrote: > > Hi Chris, > > On Tuesday, October 1, 2019 12:56:55 PM CEST Chris Hegarty wrote: >> Please find a link to the draft serialization spec for records: >> >> https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.03.ht >> ml >> >> This spec will be updated to reflect the upcoming core reflection >> changes for RecordComponent. >> >> Comments welcome. >> >> -Chris. > > Above draft says: > > """Any serialPersistentFields or serialVersionUID field declarations are also > ignored -- all record classes have a fixed serialVersionUID of 0L. > """ > > So how does this work with migration plan? When a record-like class C with > serialVersionUID != 0 is migrated to be a record, the stream produced with > class C can not be read by a program where C is a record. Or is the value of > serialVersionUID in the stream ignored when reading the stream into a record? Correct. The serialVersionUID is ignored when the local class is a record. > In that case writing class C -> reading record C is supported, but what about > writing record C -> reading class C ? Migrating from a record R to a record-like class R, then the record-like class R can be specified with an explicit serialVersionUID of 0L ( since the stream value for the serialVersionUID, of the serialized record object R, will be 0L ) > If you still want to support migration, then perhaps the default > serialVersionUID of records could be 0L always, but serialVersionUID field > would still be considered when this default needs to be overridden. So for > types that are records from day 1, users don't have to bother with > serialVersionUID fields, but if a type is migrated from class to record, this > can still be supported. The higher-order bit is that record authors don?t need to write an explicit serialVersionUID. And there is a migration strategy between record-like classes and record classes ( and vice versa ). The draft spec provides both. Do you still think that something needs to be changed here, or have any of the clarifications / comments helped? -Chris. From peter.levart at gmail.com Mon Oct 7 14:17:47 2019 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 7 Oct 2019 16:17:47 +0200 Subject: Draft Object Serialization Specification for records - serialVersionUID In-Reply-To: <2B4ED8EB-B064-4FB5-A53B-A6D113EBA83C@oracle.com> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <1671466.UgekT7RP32@cube> <2B4ED8EB-B064-4FB5-A53B-A6D113EBA83C@oracle.com> Message-ID: Hi Chris, On 10/7/19 3:31 PM, Chris Hegarty wrote: > Thank you for your feedback Peter. > >> On 6 Oct 2019, at 22:23, Peter Levart wrote: >> >> Hi Chris, >> >> On Tuesday, October 1, 2019 12:56:55 PM CEST Chris Hegarty wrote: >>> Please find a link to the draft serialization spec for records: >>> >>> https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.03.ht >>> ml >>> >>> This spec will be updated to reflect the upcoming core reflection >>> changes for RecordComponent. >>> >>> Comments welcome. >>> >>> -Chris. >> Above draft says: >> >> """Any serialPersistentFields or serialVersionUID field declarations are also >> ignored -- all record classes have a fixed serialVersionUID of 0L. >> """ >> >> So how does this work with migration plan? When a record-like class C with >> serialVersionUID != 0 is migrated to be a record, the stream produced with >> class C can not be read by a program where C is a record. Or is the value of >> serialVersionUID in the stream ignored when reading the stream into a record? > Correct. The serialVersionUID is ignored when the local class is a record. > >> In that case writing class C -> reading record C is supported, but what about >> writing record C -> reading class C ? > Migrating from a record R to a record-like class R, then the record-like class R can be specified with an explicit serialVersionUID of 0L ( since the stream value for the serialVersionUID, of the serialized record object R, will be 0L ) > >> If you still want to support migration, then perhaps the default >> serialVersionUID of records could be 0L always, but serialVersionUID field >> would still be considered when this default needs to be overridden. So for >> types that are records from day 1, users don't have to bother with >> serialVersionUID fields, but if a type is migrated from class to record, this >> can still be supported. > The higher-order bit is that record authors don?t need to write an explicit serialVersionUID. And there is a migration strategy between record-like classes and record classes ( and vice versa ). The draft spec provides both. Do you still think that something needs to be changed here, or have any of the clarifications / comments helped? > > -Chris. I was thinking of the following scenario: - there is a record-like class C with serialVersionUID != 0 in a library version v1 - new version of library v2 migrates this class C into record C - there are two network peers A and B that communicate using serialized C. A is using library version v1, B is using library version v2. Can they communicate? An example from a real world: Library v1 can in reality be JDK N Library v2 can in reality be JDK N+1 Regards, Peter From peter.levart at gmail.com Mon Oct 7 14:21:44 2019 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 7 Oct 2019 16:21:44 +0200 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> <1995499.Zq99ppJM9V@cube> Message-ID: <65d32d37-86dc-1302-8263-74b8008e5b13@gmail.com> On 10/7/19 3:31 PM, Chris Hegarty wrote: > Peter, > >> On 6 Oct 2019, at 23:07, Peter Levart wrote: >> >> On Sunday, October 6, 2019 11:38:42 PM CEST Peter Levart wrote: >>> Hi Chris, >>> >>> I think that if stream values deserialize into a record through its public >>> API (the canonical constructor which can be customized), then record >>> components that are serailzed must also be obtained from a record via its >>> public API (the accessors which can also be customized). >>> >> ...above discussion also extends to the ObjectOutputStream.writeObject method >> description that is currently written as: >> >> """If the object is a record object, the ObjectStreamClass for the class of >> the record object is written by recursively calling writeObject. It will >> appear in the stream only the first time it is referenced. A handle is >> assigned for the record object. >> >> The components of the record object are written to the stream. >> >> a. If the record object is serializable or externalizable, the record >> components are written, as if by invoking the `defaultWriteObject` >> method. >> >> b. If the object is neither serializable or externalizable, the >> `NotSerializableException` is thrown. >> >> The writeObject method then returns. >> """ >> >> So instead of "as if by invoking the `defaultWriteObject`, here you might want >> to describe how component values are obtained, etc. > Answered in another email. > >> But I wanted to comment on another thing here: "a. If the record object is >> serializable or externalizable, ..." >> >> How could record be Externalizable? It would have to implement >> writeExternal(ObjectOutput). No big deal. It would also have to have a public >> no-arg constructor. No big deal. It would have to implement >> readExternal(ObjectInput). Wait! How could a record type effectively implement >> readExternal if all record fields are final? > Yeah, Externalizable and records are just at odds. The only possible useful externalizable record is a record with no components! Externalizable is a bit of a wart here, but was included for consistency. > >> Externalizable and records don't play together well, I think. If a record type >> wishes to fully customize serialization format it still can designate a >> serialization proxy (via writeReplace()) which can be an instance of a normal >> Externalizable class for example. >> > I agree, writeReplace is the correct escape hatch for folk that want something other than the default scheme. The is why it is there. > > I?m not opposed to dropping support for Externalizable. Is that the suggestion? What should happen if one writes `record R (int x, int y) implements Externalizable { ? }` - a warning or not? maybe an error during serializing / deserializing?? I suggest nothing. He will quickly realize that he can't meaningfully implement readExternal method and abandon the attempt. I don't even think there has to be special code for instances that implement Externalizable if they are records. Regards, Peter From peter.levart at gmail.com Mon Oct 7 14:31:26 2019 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 7 Oct 2019 16:31:26 +0200 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: <1C2C454E-384E-4F28-987E-FA362256C1B5@oracle.com> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> <1C2C454E-384E-4F28-987E-FA362256C1B5@oracle.com> Message-ID: <876f109a-e490-7194-e1a9-eb3f05716256@gmail.com> On 10/7/19 3:31 PM, Chris Hegarty wrote: > Peter, > >> On 6 Oct 2019, at 22:38, Peter Levart wrote: >> >>> ... >> Here's a snipped from above draft: >> >> """The serialized form of a record object is a sequence of values derived from >> the final instance fields of the object. The stream format of a record object >> is the same as that of an ordinary object in the stream. During >> deserialization, if the local class equivalent of the specified stream class >> descriptor is a record class, then first the stream fields are read and >> reconstructed to serve as the record's component values; and second, a record >> object is created by invoking the record's canonical constructor with the >> component values as arguments (or the default value for component's type if a >> component value is absent from the stream). >> """ >> >> I think that if stream values deserialize into a record through its public API >> (the canonical constructor which can be customized), then record components >> that are serailzed must also be obtained from a record via its public API (the >> accessors which can also be customized). >> >> I think this is an important aspect which should be spelled out in the >> specification. So instead of: "The serialized form of a record object is a >> sequence of values derived from the final instance fields of the object.", the >> text should go: "The serialized form of a record object is a sequence of >> values derived from invoking the record component accessors.? > You are not wrong. In fact, I had the very same thought ( and the implementation does similar ), but we want to leave room here for deconstructors/extractors. With the wording in the current draft, it will be possible to switch the implementation without the need to update the specification. > > -Chris. > Yeah, but now the spec explicitly spells out that: "The serialized form of a record object is a sequence of values derived from the final instance fields of the object.", which is wrong. Imagine a custom accessor doing some normalization instead of canonical constructor, because record author wants to preserve information for internal logic. In the future, deconstructors/extractors would probably have to specify that they must be aligned with accessors. Perhaps the spec should speak about "component values" and then specify that currently the only way to obtain them is via accessors. Regards, Peter From chris.hegarty at oracle.com Mon Oct 7 15:36:38 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Mon, 7 Oct 2019 16:36:38 +0100 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: <65d32d37-86dc-1302-8263-74b8008e5b13@gmail.com> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> <1995499.Zq99ppJM9V@cube> <65d32d37-86dc-1302-8263-74b8008e5b13@gmail.com> Message-ID: Peter, > On 7 Oct 2019, at 15:21, Peter Levart wrote: > > ... > > I suggest nothing. He will quickly realize that he can't meaningfully implement readExternal method and abandon the attempt. I don't even think there has to be special code for instances that implement Externalizable if they are records. Ok. To confirm, no changes to the draft are needed, right? -Chris. From chris.hegarty at oracle.com Mon Oct 7 15:37:28 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Mon, 7 Oct 2019 16:37:28 +0100 Subject: Draft Object Serialization Specification for records - serialVersionUID In-Reply-To: References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <1671466.UgekT7RP32@cube> <2B4ED8EB-B064-4FB5-A53B-A6D113EBA83C@oracle.com> Message-ID: <99FAA690-5CA1-4C0D-817C-9B2A8C329228@oracle.com> Peter, > On 7 Oct 2019, at 15:17, Peter Levart wrote: > > ... > I was thinking of the following scenario: > > - there is a record-like class C with serialVersionUID != 0 in a library version v1 > - new version of library v2 migrates this class C into record C > - there are two network peers A and B that communicate using serialized C. A is using library version v1, B is using library version v2. Can they communicate? One way, yes. Both ways, no. > An example from a real world: > Library v1 can in reality be JDK N > Library v2 can in reality be JDK N+1 Good scenario. I like to think of this as the N-1 scenario ( rather than N+1 ;-) ) So, similar to what you previously suggested, maybe: 1) Allow the serialVersionUID to be explicitly declared in a record ( to support the above cross-release interoperability ). 2) The default would still be 0L, and the typical record author ( not caring about cross-release interoperation ) will not need to declare it. 3) When the local class is a record, the serialVersionUID is effectively ignored when deserializing ( no checks ) -Chris. From chris.hegarty at oracle.com Mon Oct 7 15:37:49 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Mon, 7 Oct 2019 16:37:49 +0100 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: <876f109a-e490-7194-e1a9-eb3f05716256@gmail.com> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> <1C2C454E-384E-4F28-987E-FA362256C1B5@oracle.com> <876f109a-e490-7194-e1a9-eb3f05716256@gmail.com> Message-ID: <4FAD6994-6E97-4AC9-BEBC-DEF31C255137@oracle.com> Peter, > On 7 Oct 2019, at 15:31, Peter Levart wrote: > > .. > Yeah, but now the spec explicitly spells out that: "The serialized form of a record object is a sequence of values derived from the final instance fields of the object.", which is wrong. Imagine a custom accessor doing some normalization instead of canonical constructor, because record author wants to preserve information for internal logic. In the future, deconstructors/extractors would probably have to specify that they must be aligned with accessors. Perhaps the spec should speak about "component values" and then specify that currently the only way to obtain them is via accessors. Ok, I see your point now. I?m really not sure how much customization accessors can or should do, but I do see your reasoning. Let me ponder this a little, and I?ll reply here shortly. -Chris. From brian.goetz at oracle.com Mon Oct 7 15:47:12 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 7 Oct 2019 11:47:12 -0400 Subject: sealed interface are abstract and final In-Reply-To: <1674404116.20115.1570401654754.JavaMail.zimbra@u-pem.fr> References: <1674404116.20115.1570401654754.JavaMail.zimbra@u-pem.fr> Message-ID: I agree this seems a bug.? There is no need for the ACC_FINAL bit to be set. On 10/6/2019 6:40 PM, Remi Forax wrote: > Hi all, > currently a sealed interface is abstract and final, > after having updated ASM to read sealed class/attribute, i try to test it with some sealed types running some bytecode rewriters of mine, and it was ugly. > > 2 of them flatly don't work on sealed types, because there are written with the assumption that if something final it is a class. > > Given that a sealed class is not final, why do we need interface to be final ? > > R?mi From vicente.romero at oracle.com Mon Oct 7 19:04:21 2019 From: vicente.romero at oracle.com (Vicente Romero) Date: Mon, 7 Oct 2019 15:04:21 -0400 Subject: javax.lang.model for records Message-ID: <1d8e151c-5374-1db0-d7b1-ef2395a2205a@oracle.com> Hi, We have recently made an update of the javax.lang.model implementation for records [1]. The key difference with the previous implementation is that we have made javax.lang.model.element.RecordComponentElement, a top level element in the model, a direct subinterface of j.l.m.e.Element. Previously it was extending j.l.m.e.VariableElement. Doing this seemingly minor change has implied a cascade of changes several existing APIs plus the addition of several new ones: new visitors, new scanners, etc. A specdiff of the changes can be seen at [2]. Thanks, Vicente [1] https://hg.openjdk.java.net/amber/amber/rev/cf64ea74503e [2] http://cr.openjdk.java.net/~vromero/amber/records/javax.lang.model/specdiff.00/java.compiler/module-summary.html From peter.levart at gmail.com Tue Oct 8 12:37:51 2019 From: peter.levart at gmail.com (Peter Levart) Date: Tue, 8 Oct 2019 14:37:51 +0200 Subject: Draft Object Serialization Specification for records - serialVersionUID In-Reply-To: <99FAA690-5CA1-4C0D-817C-9B2A8C329228@oracle.com> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <1671466.UgekT7RP32@cube> <2B4ED8EB-B064-4FB5-A53B-A6D113EBA83C@oracle.com> <99FAA690-5CA1-4C0D-817C-9B2A8C329228@oracle.com> Message-ID: Hi Chris, On 10/7/19 5:37 PM, Chris Hegarty wrote: > Peter, > >> On 7 Oct 2019, at 15:17, Peter Levart wrote: >> >> ... >> I was thinking of the following scenario: >> >> - there is a record-like class C with serialVersionUID != 0 in a library version v1 >> - new version of library v2 migrates this class C into record C >> - there are two network peers A and B that communicate using serialized C. A is using library version v1, B is using library version v2. Can they communicate? > One way, yes. Both ways, no. > >> An example from a real world: >> Library v1 can in reality be JDK N >> Library v2 can in reality be JDK N+1 > > Good scenario. I like to think of this as the N-1 scenario ( rather than N+1 ;-) ) > > So, similar to what you previously suggested, maybe: > 1) Allow the serialVersionUID to be explicitly declared in a record ( to support the above cross-release interoperability ). > 2) The default would still be 0L, and the typical record author ( not caring about cross-release interoperation ) will not need to declare it. > 3) When the local class is a record, the serialVersionUID is effectively ignored when deserializing ( no checks ) > On one hand, point 3 ensures that users serializing class C -> deserializing record C don't have to bother specifying explicit serialVersionUID for the record type, but OTOH it also gives false sense of assurance that new (record) serialization format is compatible with old (class) format for deserializing into instances of class. It does however cover a number of real-world use cases. So I'm not on one side or another about point 3. Regards, Peter From forax at univ-mlv.fr Wed Oct 9 13:32:04 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 9 Oct 2019 15:32:04 +0200 (CEST) Subject: Record Component attributes Message-ID: <1696878929.1465777.1570627924564.JavaMail.zimbra@u-pem.fr> Hi all, just to be sure, do we agree that a record component can be deprecated, synthetic, have a generic signature, have unknown attributes, have annotation and type annotations ? so the attributes with a special meaning are SIGNATURE, DEPRECATED, SYNTHETIC, RUNTIME_VISIBLE_ANNOTATIONS, RUNTIME_VISIBLE_TYPE_ANNOTATIONS, RUNTIME_INVISIBLE_ANNOTATIONS and RUNTIME_INVISIBLE_TYPE_ANNOTATIONS. said differently, it's all the attributes allowed on a field but CONSTANTVALUE which makes no sense on a record component. regards, R?mi From jonathan.gibbons at oracle.com Wed Oct 9 15:29:41 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 9 Oct 2019 08:29:41 -0700 Subject: Record Component attributes In-Reply-To: <1696878929.1465777.1570627924564.JavaMail.zimbra@u-pem.fr> References: <1696878929.1465777.1570627924564.JavaMail.zimbra@u-pem.fr> Message-ID: <49a210a1-c795-987f-1010-5f0c9061cb00@oracle.com> These days, deprecation is indicated by an annotation, with the DEPRECATED attribute supported as a hangover from when deprecation was indication solely by a tag in the javadoc comment. I suspect the only way to deprecate record components is via annotations, so it may not make sense to support the DEPRECATED attribute for record components. -- Jon On 10/9/19 6:32 AM, Remi Forax wrote: > Hi all, > just to be sure, do we agree that a record component can be deprecated, synthetic, have a generic signature, have unknown attributes, have annotation and type annotations ? > > so the attributes with a special meaning are > SIGNATURE, DEPRECATED, SYNTHETIC, RUNTIME_VISIBLE_ANNOTATIONS, RUNTIME_VISIBLE_TYPE_ANNOTATIONS, RUNTIME_INVISIBLE_ANNOTATIONS and RUNTIME_INVISIBLE_TYPE_ANNOTATIONS. > > said differently, it's all the attributes allowed on a field but CONSTANTVALUE which makes no sense on a record component. > > regards, > R?mi From brian.goetz at oracle.com Wed Oct 9 15:59:56 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 9 Oct 2019 11:59:56 -0400 Subject: Record Component attributes In-Reply-To: <1696878929.1465777.1570627924564.JavaMail.zimbra@u-pem.fr> References: <1696878929.1465777.1570627924564.JavaMail.zimbra@u-pem.fr> Message-ID: > just to be sure, do we agree that a record component can be deprecated, synthetic, have a generic signature, have unknown attributes, have annotation and type annotations ? Deprecated: not clear what this would mean, since removing a component is not a BC or SC change, and therefore removal seems unlikely, but I suppose deprecation could be a "stay away" warning sign for that component?? On the fence. Synthetic: I think this is a no.? The philosophy is: a record is a class whose representation and API are both derived from the state description.? Having a synthetic component would be weird (same reason we don't have inner records.) Generic signature: yes, definitely. Unknown attributes: I believe that Dan had an opinion here, as reflected in the current spec draft? Declaration and type annotations: yes, definitely. > > so the attributes with a special meaning are > SIGNATURE, DEPRECATED, SYNTHETIC, RUNTIME_VISIBLE_ANNOTATIONS, RUNTIME_VISIBLE_TYPE_ANNOTATIONS, RUNTIME_INVISIBLE_ANNOTATIONS and RUNTIME_INVISIBLE_TYPE_ANNOTATIONS. > > said differently, it's all the attributes allowed on a field but CONSTANTVALUE which makes no sense on a record component. > > regards, > R?mi From forax at univ-mlv.fr Wed Oct 9 16:44:23 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 9 Oct 2019 18:44:23 +0200 (CEST) Subject: Record Component attributes In-Reply-To: References: <1696878929.1465777.1570627924564.JavaMail.zimbra@u-pem.fr> Message-ID: <286694989.1558437.1570639463980.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Remi Forax" , "amber-spec-experts" > Envoy?: Mercredi 9 Octobre 2019 17:59:56 > Objet: Re: Record Component attributes >> just to be sure, do we agree that a record component can be deprecated, >> synthetic, have a generic signature, have unknown attributes, have annotation >> and type annotations ? > > Deprecated: not clear what this would mean, since removing a component > is not a BC or SC change, and therefore removal seems unlikely, but I > suppose deprecation could be a "stay away" warning sign for that > component?? On the fence. > > Synthetic: I think this is a no.? The philosophy is: a record is a class > whose representation and API are both derived from the state > description.? Having a synthetic component would be weird (same reason > we don't have inner records.) > > Generic signature: yes, definitely. > > Unknown attributes: I believe that Dan had an opinion here, as reflected > in the current spec draft? > > Declaration and type annotations: yes, definitely. given it's the class format representation, i will wear my JVM runtime implementer hat : There a lot of languages that have default value for parameters, so for constructor parameters, for those it makes sense to be able to deprecate a record component if at the same time you provide a default value for this component. for synthetic, a synthetic component is a component that the VM (or the reflection) sees but that javac doesn't see. Reified generics stored as parameter like in Swift is a case where you may not want javac to see your ugly refiied type/witness type/etc. R?mi > >> >> so the attributes with a special meaning are >> SIGNATURE, DEPRECATED, SYNTHETIC, RUNTIME_VISIBLE_ANNOTATIONS, >> RUNTIME_VISIBLE_TYPE_ANNOTATIONS, RUNTIME_INVISIBLE_ANNOTATIONS and >> RUNTIME_INVISIBLE_TYPE_ANNOTATIONS. >> >> said differently, it's all the attributes allowed on a field but CONSTANTVALUE >> which makes no sense on a record component. >> >> regards, > > R?mi From forax at univ-mlv.fr Wed Oct 9 18:34:54 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 9 Oct 2019 20:34:54 +0200 (CEST) Subject: Record Component attributes In-Reply-To: <286694989.1558437.1570639463980.JavaMail.zimbra@u-pem.fr> References: <1696878929.1465777.1570627924564.JavaMail.zimbra@u-pem.fr> <286694989.1558437.1570639463980.JavaMail.zimbra@u-pem.fr> Message-ID: <1119354537.1583097.1570646094971.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Remi Forax" > ?: "Brian Goetz" > Cc: "amber-spec-experts" > Envoy?: Mercredi 9 Octobre 2019 18:44:23 > Objet: Re: Record Component attributes > ----- Mail original ----- >> De: "Brian Goetz" >> ?: "Remi Forax" , "amber-spec-experts" >> >> Envoy?: Mercredi 9 Octobre 2019 17:59:56 >> Objet: Re: Record Component attributes > >>> just to be sure, do we agree that a record component can be deprecated, >>> synthetic, have a generic signature, have unknown attributes, have annotation >>> and type annotations ? >> >> Deprecated: not clear what this would mean, since removing a component >> is not a BC or SC change, and therefore removal seems unlikely, but I >> suppose deprecation could be a "stay away" warning sign for that >> component?? On the fence. >> >> Synthetic: I think this is a no.? The philosophy is: a record is a class >> whose representation and API are both derived from the state >> description.? Having a synthetic component would be weird (same reason >> we don't have inner records.) >> >> Generic signature: yes, definitely. >> >> Unknown attributes: I believe that Dan had an opinion here, as reflected >> in the current spec draft? >> >> Declaration and type annotations: yes, definitely. > > given it's the class format representation, i will wear my JVM runtime > implementer hat : > > There a lot of languages that have default value for parameters, so for > constructor parameters, > for those it makes sense to be able to deprecate a record component if at the > same time you provide a default value for this component. > > for synthetic, a synthetic component is a component that the VM (or the > reflection) sees but that javac doesn't see. Reified generics stored as > parameter like in Swift is a case where you may not want javac to see your ugly > refiied type/witness type/etc. and answering to myself, javac doesn't directly access to the record component, it accesses to the generated fields/methods so making the record component synthetic or not has no impact on javac, so marking a record component Synthetic seems useless. R?mi > >> >>> >>> so the attributes with a special meaning are >>> SIGNATURE, DEPRECATED, SYNTHETIC, RUNTIME_VISIBLE_ANNOTATIONS, >>> RUNTIME_VISIBLE_TYPE_ANNOTATIONS, RUNTIME_INVISIBLE_ANNOTATIONS and >>> RUNTIME_INVISIBLE_TYPE_ANNOTATIONS. >>> >>> said differently, it's all the attributes allowed on a field but CONSTANTVALUE >>> which makes no sense on a record component. >>> >>> regards, > > > R?mi From brian.goetz at oracle.com Wed Oct 9 18:52:41 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 9 Oct 2019 14:52:41 -0400 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: <1C2C454E-384E-4F28-987E-FA362256C1B5@oracle.com> References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> <1C2C454E-384E-4F28-987E-FA362256C1B5@oracle.com> Message-ID: > You are not wrong. In fact, I had the very same thought ( and the implementation does similar ), but we want to leave room here for deconstructors/extractors. With the wording in the current draft, it will be possible to switch the implementation without the need to update the specification. I think there is room to support the future.? Here are some ways we could extract the state from a record for serialization: ?A. Scrape the fields. ?B. Call the field accessors. ?C. Invoke the canonical deconstructor (when we have them.) ?D. Invoke a serialization-specific pattern if there is one (when we support them.) Note that in a case of `record R(...) { }`, these are all the same -- the default accessors return the field values, and the default canonical deconstructor invokes the accessors. Clearly, if the user provides an explicit serialization member (whatever that looks like), we should use that in preference to "default" serialization; this is true for classes and records alike, it's just that the default behavior differs between classes and records.? So when we get to New And Improved Serialization, D presents no migration problem; we can say "if there is a serialization pattern, use that, otherwise..." We can make the same argument for C, since in the absence of an explicit dtor, which you can't write now, what you'd get from an implicit dtor is the result of B.? Same story: "if there is a canonical ctor, use that." The real question is A vs B.? One can make an argument that serialization is about raw object state, which means that field-scraping is OK.? Or one can make the argument that we are trying to make serialization safer, so we should prefer the accessor (when there is one.)? Most of the time, though, if there is a nontrivial accessor, all it will do is make a copy (say, if the corresponding component is an array), so going through the accessor is a bit of a wasted effort. From brian.goetz at oracle.com Wed Oct 9 21:10:40 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 9 Oct 2019 17:10:40 -0400 Subject: [records] Native members Message-ID: <777737f5-43a3-ef4d-8ff9-025cd395ed74@oracle.com> Jon has pointed out that it is possible to declare a record with native methods and/or constructor. Let's just add `native` to the set of modifiers that are not allowed on members of records.... From brian.goetz at oracle.com Wed Oct 9 21:26:26 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 9 Oct 2019 17:26:26 -0400 Subject: [sealed] Sealed local classes? Message-ID: It is allowable, though somewhat silly, to put the `final` modifier on local classes. From a hierarchy-protection point of view, allowing local classes to be `sealed` is also silly, as it cannot be extended from outside the method anyway, and even if it could, such types can't show up in APIs that are accessible from outside. From an exhaustiveness point of view, though, one can imagine having a sealed local hierarchy (sum of records) that will be switched over within the method, though one would have to work pretty hard to imagine that. Note that a local class cannot be a subtype of a sealed type declared outside the same method (*), since it can't be denoted in the permits clause. (*) unless the permits clause is inferred.? Yuck.? Now a mangled name would go into the PermittedSubtypes attribute. Proposal: ban `sealed` and `non-sealed` modifiers on _local_ classes and interfaces. From brian.goetz at oracle.com Wed Oct 9 21:35:48 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 9 Oct 2019 17:35:48 -0400 Subject: [sealed] Sealed local classes? In-Reply-To: References: Message-ID: <896473e3-a6df-b8d4-91c9-779bf70954a2@oracle.com> > Proposal: ban `sealed` and `non-sealed` modifiers on _local_ classes > and interfaces. And we would want to extend the ban we have for the other two forms of "subclasses inside implementations", lambdas and inner classes, to local classes. From forax at univ-mlv.fr Wed Oct 9 22:09:49 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 10 Oct 2019 00:09:49 +0200 (CEST) Subject: [records] Native members In-Reply-To: <777737f5-43a3-ef4d-8ff9-025cd395ed74@oracle.com> References: <777737f5-43a3-ef4d-8ff9-025cd395ed74@oracle.com> Message-ID: <2098674730.1615906.1570658989901.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "amber-spec-experts" > Envoy?: Mercredi 9 Octobre 2019 23:10:40 > Objet: [records] Native members > Jon has pointed out that it is possible to declare a record with native > methods and/or constructor. > > Let's just add `native` to the set of modifiers that are not allowed on > members of records.... You have not provided a rational, maybe there is an obvious reason that i can not see ? For me, it's fine to have a private static native method inside a record. Obviously, having native method which is an instance method or a constructor is a bad idea but it's a bad idea for classes, interfaces and records, so i don't see why we should fix that for record without fixing it for classes and interfaces too. R?mi From forax at univ-mlv.fr Wed Oct 9 22:13:00 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 10 Oct 2019 00:13:00 +0200 (CEST) Subject: [sealed] Sealed local classes? In-Reply-To: References: Message-ID: <630600326.1616381.1570659180159.JavaMail.zimbra@u-pem.fr> I agree, PermittedSubtypes should only contains stable names. R?mi ----- Mail original ----- > De: "Brian Goetz" > ?: "amber-spec-experts" > Envoy?: Mercredi 9 Octobre 2019 23:26:26 > Objet: [sealed] Sealed local classes? > It is allowable, though somewhat silly, to put the `final` modifier on > local classes. > > From a hierarchy-protection point of view, allowing local classes to be > `sealed` is also silly, as it cannot be extended from outside the method > anyway, and even if it could, such types can't show up in APIs that are > accessible from outside. > > From an exhaustiveness point of view, though, one can imagine having a > sealed local hierarchy (sum of records) that will be switched over > within the method, though one would have to work pretty hard to imagine > that. > > Note that a local class cannot be a subtype of a sealed type declared > outside the same method (*), since it can't be denoted in the permits > clause. > > (*) unless the permits clause is inferred.? Yuck.? Now a mangled name > would go into the PermittedSubtypes attribute. > > Proposal: ban `sealed` and `non-sealed` modifiers on _local_ classes and > interfaces. From forax at univ-mlv.fr Wed Oct 9 22:13:40 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 10 Oct 2019 00:13:40 +0200 (CEST) Subject: [sealed] Sealed local classes? In-Reply-To: <896473e3-a6df-b8d4-91c9-779bf70954a2@oracle.com> References: <896473e3-a6df-b8d4-91c9-779bf70954a2@oracle.com> Message-ID: <1458956846.1616463.1570659220610.JavaMail.zimbra@u-pem.fr> I agree, PermittedSubtypes should only contain stable names :) R?mi ----- Mail original ----- > De: "Brian Goetz" > ?: "amber-spec-experts" > Envoy?: Mercredi 9 Octobre 2019 23:35:48 > Objet: Re: [sealed] Sealed local classes? >> Proposal: ban `sealed` and `non-sealed` modifiers on _local_ classes >> and interfaces. > > And we would want to extend the ban we have for the other two forms of > "subclasses inside implementations", lambdas and inner classes, to local > classes. From maurizio.cimadamore at oracle.com Wed Oct 9 23:22:20 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 10 Oct 2019 00:22:20 +0100 Subject: [sealed] Sealed local classes? In-Reply-To: References: Message-ID: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> Good catch! I fully support the restriction. In your other email I guess you are referring to anonymous classes implementing a sealed interface, right? E.g. sealed interface Foo { ??? void m(); ??? /* static final */ Foo f1 = new Foo() { ... } ??? /* static final */ Foo f2 = () -> {}; } That is, this should be rejected on same ground - given that inference would end up putting mangled type names in the permits clause (well, at least for the anonymous, in the case of the lambda there's not even a name ;-)). Dunno about the above code - it's not completely unreasonable (it's not hard to imagine a functional interface having some pre-wired default value - e.g. like Predicate::FALSE). Another angle is, instead of banning,these weird subclasses, we just don't add them to the permits clause (*) (*) there's also a technical reason as to why inferring permitted types based on things inside field initializers and method bodies is not sound: again it has to do with annotation processing. Presumably you want all your inference completed before annotation processors are run. But, by design, annotation processor only requires declarations to be processed, not entire method bodies. So it would not be possible, under the current regime at least, to gather up all permitted types inside all method bodies _before_ annotation processing. Maurizio On 09/10/2019 22:26, Brian Goetz wrote: > It is allowable, though somewhat silly, to put the `final` modifier on > local classes. > > From a hierarchy-protection point of view, allowing local classes to > be `sealed` is also silly, as it cannot be extended from outside the > method anyway, and even if it could, such types can't show up in APIs > that are accessible from outside. > > From an exhaustiveness point of view, though, one can imagine having a > sealed local hierarchy (sum of records) that will be switched over > within the method, though one would have to work pretty hard to > imagine that. > > Note that a local class cannot be a subtype of a sealed type declared > outside the same method (*), since it can't be denoted in the permits > clause. > > (*) unless the permits clause is inferred.? Yuck.? Now a mangled name > would go into the PermittedSubtypes attribute. > > Proposal: ban `sealed` and `non-sealed` modifiers on _local_ classes > and interfaces. From brian.goetz at oracle.com Thu Oct 10 00:50:30 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 9 Oct 2019 20:50:30 -0400 Subject: [sealed] Sealed local classes? In-Reply-To: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> References: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> Message-ID: > In your other email I guess you are referring to anonymous classes > implementing a sealed interface, right? E.g. > > sealed interface Foo { > ??? void m(); > > ??? /* static final */ Foo f1 = new Foo() { ... } > ??? /* static final */ Foo f2 = () -> {}; > > } Right.? We already restrict anon and lambda instances of the sealed type.? Not only can't we stably write down their types in the PS attribute, but even if we could, it's so easy to accidentally lose exhaustiveness. > (*) there's also a technical reason as to why inferring permitted > types based on things inside field initializers and method bodies is > not sound: again it has to do with annotation processing. Presumably > you want all your inference completed before annotation processors are > run. But, by design, annotation processor only requires declarations > to be processed, not entire method bodies. So it would not be > possible, under the current regime at least, to gather up all > permitted types inside all method bodies _before_ annotation processing. Yep. From maurizio.cimadamore at oracle.com Thu Oct 10 08:45:00 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 10 Oct 2019 09:45:00 +0100 Subject: [sealed] Sealed local classes? In-Reply-To: References: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> Message-ID: <6be64f8f-02ad-43fc-bbe8-0410bbd2be2b@oracle.com> On 10/10/2019 01:50, Brian Goetz wrote: > Right. We already restrict anon and lambda instances of the sealed > type. Not only can't we stably write down their types in the PS > attribute, but even if we could, it's so easy to accidentally lose > exhaustiveness. This is a very good point; if I have type T = A | B | C, but then I have 'anonymous' Ts flying around, all switches assuming A|B|C are no longer exhaustive. Maurizio From maurizio.cimadamore at oracle.com Thu Oct 10 08:58:35 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 10 Oct 2019 09:58:35 +0100 Subject: Record Component attributes In-Reply-To: <1119354537.1583097.1570646094971.JavaMail.zimbra@u-pem.fr> References: <1696878929.1465777.1570627924564.JavaMail.zimbra@u-pem.fr> <286694989.1558437.1570639463980.JavaMail.zimbra@u-pem.fr> <1119354537.1583097.1570646094971.JavaMail.zimbra@u-pem.fr> Message-ID: On 09/10/2019 19:34, Remi Forax wrote: > > ----- Mail original ----- >> De: "Remi Forax" >> ?: "Brian Goetz" >> Cc: "amber-spec-experts" >> Envoy?: Mercredi 9 Octobre 2019 18:44:23 >> Objet: Re: Record Component attributes >> ----- Mail original ----- >>> De: "Brian Goetz" >>> ?: "Remi Forax" , "amber-spec-experts" >>> >>> Envoy?: Mercredi 9 Octobre 2019 17:59:56 >>> Objet: Re: Record Component attributes >>>> just to be sure, do we agree that a record component can be deprecated, >>>> synthetic, have a generic signature, have unknown attributes, have annotation >>>> and type annotations ? >>> Deprecated: not clear what this would mean, since removing a component >>> is not a BC or SC change, and therefore removal seems unlikely, but I >>> suppose deprecation could be a "stay away" warning sign for that >>> component?? On the fence. >>> >>> Synthetic: I think this is a no.? The philosophy is: a record is a class >>> whose representation and API are both derived from the state >>> description.? Having a synthetic component would be weird (same reason >>> we don't have inner records.) >>> >>> Generic signature: yes, definitely. >>> >>> Unknown attributes: I believe that Dan had an opinion here, as reflected >>> in the current spec draft? >>> >>> Declaration and type annotations: yes, definitely. >> given it's the class format representation, i will wear my JVM runtime >> implementer hat : >> >> There a lot of languages that have default value for parameters, so for >> constructor parameters, >> for those it makes sense to be able to deprecate a record component if at the >> same time you provide a default value for this component. >> >> for synthetic, a synthetic component is a component that the VM (or the >> reflection) sees but that javac doesn't see. Reified generics stored as >> parameter like in Swift is a case where you may not want javac to see your ugly >> refiied type/witness type/etc. > and answering to myself, > javac doesn't directly access to the record component, it accesses to the generated fields/methods so making the record component synthetic or not has no impact on javac, so marking a record component Synthetic seems useless. I think the problem of this question is not whether it would make sense for Java right now, but whether it could make sense for other languages (or even Java of tomorrow) to use records as a translation target; now, this seems not super likely given that records are a restriction of a more general construct (class), so a compiler would probably prefer the more general target. Synthetic can be useful in situations where there are 'hidden' components that are injected by javac, pretty much as a hidden this$0 is added on all inner classes. It's there, but you are not allowed to see it (or match on it), not from the language, not from core reflection. Right now we don't envisage any purpose for doing something like this, but I also don't immediately see a reason for shutting down the door on it either. Perhaps this _hidden_ nature of synthetic components could be used as a motivation as to why we don't like ACC_SYNTHETIC to be added in the mix - on the one hand we're saying "records are all about transparent state", and, with synthetic components, this goes down the drain a bit, as there are hidden parts of the state you can't see or pattern match. As for DEPRECATED, it doesn't make a lot of sense, but not sure whether source/binary compatibility is a good explanation; after all, removing a class field is neither BC nor SC (for clients that refer to that field). The problem with records is just made worse by the fact that, with pattern matching and, deconstructor patterns we envision that 'accessing all components' will be a routine operation. But it's a quantitative change, not a qualitative one, IMHO. Maurizio > > R?mi > >>>> so the attributes with a special meaning are >>>> SIGNATURE, DEPRECATED, SYNTHETIC, RUNTIME_VISIBLE_ANNOTATIONS, >>>> RUNTIME_VISIBLE_TYPE_ANNOTATIONS, RUNTIME_INVISIBLE_ANNOTATIONS and >>>> RUNTIME_INVISIBLE_TYPE_ANNOTATIONS. >>>> >>>> said differently, it's all the attributes allowed on a field but CONSTANTVALUE >>>> which makes no sense on a record component. >>>> >>>> regards, >>>> R?mi From forax at univ-mlv.fr Thu Oct 10 10:37:55 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 10 Oct 2019 12:37:55 +0200 (CEST) Subject: PatternHandle in record Message-ID: <466696660.1827544.1570703875556.JavaMail.zimbra@u-pem.fr> Hi all, ASM doesn't like too much weird method names, exactly the ASMifier, that take a binary class and generate the Java code that will create the same binary class, doesn't work well with the method named "\%pattern\%RecordSubType\%(ILjava\|lang\|String\?)". I have two questions: - why do we need a description of a pattern inside a record class given that the Record attribute already provides that description (that is accessible using Class.getRecordComponents()) ? A record is already able to describe itself, that's its purpose, why do we need another way of describing it ? - why the method that return a PatternHandle is using a mangled name like this ? Given that the constant dynamic also use the same encoding ?? R?mi public static java.lang.runtime.PatternHandle \%pattern\%RecordSubType\%(ILjava\|lang\|String\?)(); descriptor: ()Ljava/lang/runtime/PatternHandle; flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=0, args_size=0 0: ldc #29 // Dynamic #1:"\\%pattern\\%RecordSubType\\%(ILjava\\|lang\\|String\\?)":Ljava/lang/runtime/PatternHandle; 2: areturn LineNumberTable: line 9: 0 From forax at univ-mlv.fr Thu Oct 10 14:15:03 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 10 Oct 2019 16:15:03 +0200 (CEST) Subject: Fields and methods of a record are marked MANDATED Message-ID: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> Hi all, fields and methods of a record are marked ACC_MANDATED which contradict JLS 13.1.12 that explains that you can not use ACC_MANDATED on field and method. regards, R?mi From brian.goetz at oracle.com Thu Oct 10 15:50:37 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 Oct 2019 11:50:37 -0400 Subject: Fields and methods of a record are marked MANDATED In-Reply-To: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> References: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> Message-ID: <0C47CD99-EAA3-4B6B-AAA7-0D8668E8025D@oracle.com> We should match the behavior of methods like `Enum::values`. > On Oct 10, 2019, at 10:15 AM, Remi Forax wrote: > > Hi all, > fields and methods of a record are marked ACC_MANDATED which contradict JLS 13.1.12 that explains that you can not use ACC_MANDATED on field and method. > > regards, > R?mi > From brian.goetz at oracle.com Thu Oct 10 15:57:46 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 Oct 2019 11:57:46 -0400 Subject: PatternHandle in record In-Reply-To: <466696660.1827544.1570703875556.JavaMail.zimbra@u-pem.fr> References: <466696660.1827544.1570703875556.JavaMail.zimbra@u-pem.fr> Message-ID: <2BE3FD4D-E971-4336-BA62-2E555D1C8337@oracle.com> The answers to these questions are beyond the scope of the record discussion, and while I?m happy to discuss them at some point, I would like to focus on getting records out the door right now, so I ask your forbearance in not diving down the pattern translation rabbit hole right now. The places where records touch pattern matching will likely be stripped out for the first preview of records; they are there right now as a means of validating how all the pieces fit together. Because deconstruction patterns won?t be ready for the first preview, we?ll likely back these pieces out. But, these are not _descriptions_ of the pattern ? they are the _implementation_ of the pattern. And remember, patterns will go far deeper than mere deconstruction patterns (which yes, could be special-cased at the use site for records); they are executable class members, and can be virtual. So there needs to be support in the class file for linking to patterns; the strategy that is currently on the table is that patterns are represented in the class file by methods that yield a Pattern constant, that static patterns are represented by static methods, and instance patterns are represented by instance methods. And because a pattern with the same name can be overloaded with multiple signatures, we need a stable name to invoke that captures not only the name but also the descriptor. > On Oct 10, 2019, at 6:37 AM, Remi Forax wrote: > > Hi all, > ASM doesn't like too much weird method names, > exactly the ASMifier, that take a binary class and generate the Java code that will create the same binary class, doesn't work well with the method named "\%pattern\%RecordSubType\%(ILjava\|lang\|String\?)". > > I have two questions: > - why do we need a description of a pattern inside a record class given that the Record attribute already provides that description (that is accessible using Class.getRecordComponents()) ? > A record is already able to describe itself, that's its purpose, why do we need another way of describing it ? > - why the method that return a PatternHandle is using a mangled name like this ? > Given that the constant dynamic also use the same encoding ?? > > R?mi > > public static java.lang.runtime.PatternHandle \%pattern\%RecordSubType\%(ILjava\|lang\|String\?)(); > descriptor: ()Ljava/lang/runtime/PatternHandle; > flags: (0x0009) ACC_PUBLIC, ACC_STATIC > Code: > stack=1, locals=0, args_size=0 > 0: ldc #29 // Dynamic #1:"\\%pattern\\%RecordSubType\\%(ILjava\\|lang\\|String\\?)":Ljava/lang/runtime/PatternHandle; > 2: areturn > LineNumberTable: > line 9: 0 From joe.darcy at oracle.com Thu Oct 10 16:06:15 2019 From: joe.darcy at oracle.com (Joe Darcy) Date: Thu, 10 Oct 2019 09:06:15 -0700 Subject: Fields and methods of a record are marked MANDATED In-Reply-To: <0C47CD99-EAA3-4B6B-AAA7-0D8668E8025D@oracle.com> References: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> <0C47CD99-EAA3-4B6B-AAA7-0D8668E8025D@oracle.com> Message-ID: <4e9dbd47-8507-945f-9721-18ea3274b225@oracle.com> A mandated construct is one that is mandated by the specification, but not explicitly declared. Constructs of that sort have been in the platform since the beginning, such as default constructors. ACC_MANDATED was added to the platform only more recently and has some exposure through javax.lang.model. I recommend going forward ACC_MANDATED to be used more widely, on all the mandated structures, including the values methods on enum types, etc. Cheers, -Joe On 10/10/2019 8:50 AM, Brian Goetz wrote: > We should match the behavior of methods like `Enum::values`. > >> On Oct 10, 2019, at 10:15 AM, Remi Forax wrote: >> >> Hi all, >> fields and methods of a record are marked ACC_MANDATED which contradict JLS 13.1.12 that explains that you can not use ACC_MANDATED on field and method. >> >> regards, >> R?mi >> From brian.goetz at oracle.com Thu Oct 10 16:09:41 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 Oct 2019 12:09:41 -0400 Subject: Fields and methods of a record are marked MANDATED In-Reply-To: <4e9dbd47-8507-945f-9721-18ea3274b225@oracle.com> References: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> <0C47CD99-EAA3-4B6B-AAA7-0D8668E8025D@oracle.com> <4e9dbd47-8507-945f-9721-18ea3274b225@oracle.com> Message-ID: Under that interpretation, that leaves record members in a funny place, since a given mandated member (e.g., an accessor for a component) _might_ have been explicit in the source, or might not have been. Should ACC_MANDATED describe the member descriptor (?spec mandates a member with this descriptor?) or only the implementation (?the source didn?t have it, but its here in the byte code?)? In the latter interpretation, the presence of ACC_MANDATED on a mandated member would basically be random, based on implementation-of-the-day, which seems wrong. > On Oct 10, 2019, at 12:06 PM, Joe Darcy wrote: > > A mandated construct is one that is mandated by the specification, but not explicitly declared. Constructs of that sort have been in the platform since the beginning, such as default constructors. ACC_MANDATED was added to the platform only more recently and has some exposure through javax.lang.model. > > I recommend going forward ACC_MANDATED to be used more widely, on all the mandated structures, including the values methods on enum types, etc. > > Cheers, > > -Joe > > On 10/10/2019 8:50 AM, Brian Goetz wrote: >> We should match the behavior of methods like `Enum::values`. >> >>> On Oct 10, 2019, at 10:15 AM, Remi Forax wrote: >>> >>> Hi all, >>> fields and methods of a record are marked ACC_MANDATED which contradict JLS 13.1.12 that explains that you can not use ACC_MANDATED on field and method. >>> >>> regards, >>> R?mi >>> From forax at univ-mlv.fr Thu Oct 10 17:05:41 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 10 Oct 2019 19:05:41 +0200 (CEST) Subject: PatternHandle in record In-Reply-To: <2BE3FD4D-E971-4336-BA62-2E555D1C8337@oracle.com> References: <466696660.1827544.1570703875556.JavaMail.zimbra@u-pem.fr> <2BE3FD4D-E971-4336-BA62-2E555D1C8337@oracle.com> Message-ID: <1607064913.2039244.1570727141251.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Remi Forax" > Cc: "amber-spec-experts" > Envoy?: Jeudi 10 Octobre 2019 17:57:46 > Objet: Re: PatternHandle in record > The answers to these questions are beyond the scope of the record discussion, > and while I?m happy to discuss them at some point, I would like to focus on > getting records out the door right now, so I ask your forbearance in not diving > down the pattern translation rabbit hole right now. i agree, let's release the records first. > > The places where records touch pattern matching will likely be stripped out for > the first preview of records; they are there right now as a means of validating > how all the pieces fit together. Because deconstruction patterns won?t be > ready for the first preview, we?ll likely back these pieces out. yes > > But, these are not _descriptions_ of the pattern ? they are the _implementation_ > of the pattern. And remember, patterns will go far deeper than mere > deconstruction patterns (which yes, could be special-cased at the use site for > records); they are executable class members, and can be virtual. So there > needs to be support in the class file for linking to patterns; the strategy > that is currently on the table is that patterns are represented in the class > file by methods that yield a Pattern constant, that static patterns are > represented by static methods, and instance patterns are represented by > instance methods. And because a pattern with the same name can be overloaded > with multiple signatures, we need a stable name to invoke that captures not > only the name but also the descriptor. yes, patterns may be more general and virtual but i was talking about the one that is currently generated inside a record classfile, and that one only describes statically the record, something i think is not necessary given you can always ask at runtime is a class is a record or not. so it seems, we can agree that an automatically generated pattern is not useful, at least the first version of the records. R?mi > > > >> On Oct 10, 2019, at 6:37 AM, Remi Forax wrote: >> >> Hi all, >> ASM doesn't like too much weird method names, >> exactly the ASMifier, that take a binary class and generate the Java code that >> will create the same binary class, doesn't work well with the method named >> "\%pattern\%RecordSubType\%(ILjava\|lang\|String\?)". >> >> I have two questions: >> - why do we need a description of a pattern inside a record class given that the >> Record attribute already provides that description (that is accessible using >> Class.getRecordComponents()) ? >> A record is already able to describe itself, that's its purpose, why do we need >> another way of describing it ? >> - why the method that return a PatternHandle is using a mangled name like this ? >> Given that the constant dynamic also use the same encoding ?? >> >> R?mi >> >> public static java.lang.runtime.PatternHandle >> \%pattern\%RecordSubType\%(ILjava\|lang\|String\?)(); >> descriptor: ()Ljava/lang/runtime/PatternHandle; >> flags: (0x0009) ACC_PUBLIC, ACC_STATIC >> Code: >> stack=1, locals=0, args_size=0 >> 0: ldc #29 // Dynamic >> #1:"\\%pattern\\%RecordSubType\\%(ILjava\\|lang\\|String\\?)":Ljava/lang/runtime/PatternHandle; >> 2: areturn >> LineNumberTable: > > line 9: 0 From alex.buckley at oracle.com Thu Oct 10 17:41:31 2019 From: alex.buckley at oracle.com (Alex Buckley) Date: Thu, 10 Oct 2019 10:41:31 -0700 Subject: Fields and methods of a record are marked MANDATED In-Reply-To: References: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> <0C47CD99-EAA3-4B6B-AAA7-0D8668E8025D@oracle.com> <4e9dbd47-8507-945f-9721-18ea3274b225@oracle.com> Message-ID: Enum types are specified such that a `values` method is always implicitly declared. (If you declare one explicitly, you have two method declarations with override-equivalent signatures, which is an error per JLS 8.4.) Accordingly, the corresponding method in the class file should always be marked as mandated. Sadly we don't have room for an ACC_MANDATED flag in `method_info`, but morally the method is mandated and Core Reflection should expose that fact. Record types are specified more sensitively: a component's accessor is implicitly declared if and only if it isn't explicitly declared. (Same deal as the default constructor of a class.) If a component's accessor is explicitly declared, then there's nothing more to say; if it's implicitly declared, then it should be marked as mandated. I wouldn't characterize this as member descriptor v. member implementation, because that sounds like "the signature" v. "the body". Fundamentally, the topic at hand is component accessors, which are non-abstract methods of non-abstract classes; for such methods of such classes, EITHER you declare both the signature and the body (in which case there's an explicit declaration of both signature and body) OR you declare neither (in which case there's an implicit declaration of both signature and body). Ordinary consumers of the record type are happy because they can be assured that component accessors are always declared (i.e., the compiler will always find the signature, the VM will always link the descriptor, and the subsequent execution of the linked method will always do something useful), while reflective consumers of the record type are happy because they can tell whether a component accessor (the signature and body as one undivided entity) was declared explicitly or implicitly. You say "random", I say "accurate". Alex On 10/10/2019 9:09 AM, Brian Goetz wrote: > Under that interpretation, that leaves record members in a funny place, since a given mandated member (e.g., an accessor for a component) _might_ have been explicit in the source, or might not have been. Should ACC_MANDATED describe the member descriptor (?spec mandates a member with this descriptor?) or only the implementation (?the source didn?t have it, but its here in the byte code?)? In the latter interpretation, the presence of ACC_MANDATED on a mandated member would basically be random, based on implementation-of-the-day, which seems wrong. > >> On Oct 10, 2019, at 12:06 PM, Joe Darcy wrote: >> >> A mandated construct is one that is mandated by the specification, but not explicitly declared. Constructs of that sort have been in the platform since the beginning, such as default constructors. ACC_MANDATED was added to the platform only more recently and has some exposure through javax.lang.model. >> >> I recommend going forward ACC_MANDATED to be used more widely, on all the mandated structures, including the values methods on enum types, etc. >> >> Cheers, >> >> -Joe >> >> On 10/10/2019 8:50 AM, Brian Goetz wrote: >>> We should match the behavior of methods like `Enum::values`. >>> >>>> On Oct 10, 2019, at 10:15 AM, Remi Forax wrote: >>>> >>>> Hi all, >>>> fields and methods of a record are marked ACC_MANDATED which contradict JLS 13.1.12 that explains that you can not use ACC_MANDATED on field and method. >>>> >>>> regards, >>>> R?mi >>>> > From jonathan.gibbons at oracle.com Thu Oct 10 18:09:59 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 10 Oct 2019 11:09:59 -0700 Subject: Fields and methods of a record are marked MANDATED In-Reply-To: References: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> <0C47CD99-EAA3-4B6B-AAA7-0D8668E8025D@oracle.com> <4e9dbd47-8507-945f-9721-18ea3274b225@oracle.com> Message-ID: <9c4b7e93-9a3d-7c20-1252-f29903542b2a@oracle.com> Brian, This distinction is covered under javax.lang.model.util.Elements.Origin. https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/lang/model/util/Elements.Origin.html In other words, you should be able to determine if a member was provided explicitly in source code, or provided by the compiler. -- Jon On 10/10/19 9:09 AM, Brian Goetz wrote: > Under that interpretation, that leaves record members in a funny place, since a given mandated member (e.g., an accessor for a component) _might_ have been explicit in the source, or might not have been. Should ACC_MANDATED describe the member descriptor (?spec mandates a member with this descriptor?) or only the implementation (?the source didn?t have it, but its here in the byte code?)? In the latter interpretation, the presence of ACC_MANDATED on a mandated member would basically be random, based on implementation-of-the-day, which seems wrong. > >> On Oct 10, 2019, at 12:06 PM, Joe Darcy wrote: >> >> A mandated construct is one that is mandated by the specification, but not explicitly declared. Constructs of that sort have been in the platform since the beginning, such as default constructors. ACC_MANDATED was added to the platform only more recently and has some exposure through javax.lang.model. >> >> I recommend going forward ACC_MANDATED to be used more widely, on all the mandated structures, including the values methods on enum types, etc. >> >> Cheers, >> >> -Joe >> >> On 10/10/2019 8:50 AM, Brian Goetz wrote: >>> We should match the behavior of methods like `Enum::values`. >>> >>>> On Oct 10, 2019, at 10:15 AM, Remi Forax wrote: >>>> >>>> Hi all, >>>> fields and methods of a record are marked ACC_MANDATED which contradict JLS 13.1.12 that explains that you can not use ACC_MANDATED on field and method. >>>> >>>> regards, >>>> R?mi >>>> From forax at univ-mlv.fr Thu Oct 10 18:33:50 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 10 Oct 2019 20:33:50 +0200 (CEST) Subject: Fields and methods of a record are marked MANDATED In-Reply-To: References: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> <0C47CD99-EAA3-4B6B-AAA7-0D8668E8025D@oracle.com> <4e9dbd47-8507-945f-9721-18ea3274b225@oracle.com> Message-ID: <12072255.2052383.1570732430150.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Alex Buckley" > ?: "amber-spec-experts" > Envoy?: Jeudi 10 Octobre 2019 19:41:31 > Objet: Re: Fields and methods of a record are marked MANDATED > Enum types are specified such that a `values` method is always > implicitly declared. (If you declare one explicitly, you have two method > declarations with override-equivalent signatures, which is an error per > JLS 8.4.) Accordingly, the corresponding method in the class file should > always be marked as mandated. Sadly we don't have room for an > ACC_MANDATED flag in `method_info`, but morally the method is mandated > and Core Reflection should expose that fact. ACC_MANDATED is 0x8000 so you can use it on methods. But not on class because it's ACC_MODULE. [...] > > Alex R?mi > > On 10/10/2019 9:09 AM, Brian Goetz wrote: >> Under that interpretation, that leaves record members in a funny place, since a >> given mandated member (e.g., an accessor for a component) _might_ have been >> explicit in the source, or might not have been. Should ACC_MANDATED describe >> the member descriptor (?spec mandates a member with this descriptor?) or only >> the implementation (?the source didn?t have it, but its here in the byte >> code?)? In the latter interpretation, the presence of ACC_MANDATED on a >> mandated member would basically be random, based on implementation-of-the-day, >> which seems wrong. >> >>> On Oct 10, 2019, at 12:06 PM, Joe Darcy wrote: >>> >>> A mandated construct is one that is mandated by the specification, but not >>> explicitly declared. Constructs of that sort have been in the platform since >>> the beginning, such as default constructors. ACC_MANDATED was added to the >>> platform only more recently and has some exposure through javax.lang.model. >>> >>> I recommend going forward ACC_MANDATED to be used more widely, on all the >>> mandated structures, including the values methods on enum types, etc. >>> >>> Cheers, >>> >>> -Joe >>> >>> On 10/10/2019 8:50 AM, Brian Goetz wrote: >>>> We should match the behavior of methods like `Enum::values`. >>>> >>>>> On Oct 10, 2019, at 10:15 AM, Remi Forax wrote: >>>>> >>>>> Hi all, >>>>> fields and methods of a record are marked ACC_MANDATED which contradict JLS >>>>> 13.1.12 that explains that you can not use ACC_MANDATED on field and method. >>>>> >>>>> regards, >>>>> R?mi >>>>> From forax at univ-mlv.fr Thu Oct 10 21:34:31 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 10 Oct 2019 23:34:31 +0200 (CEST) Subject: Class.getRecordComponent() javadoc doesn't specify its behavior if the accessor of a record component is not present In-Reply-To: <0075df55-fd45-23b8-738f-4a58fc3c6a51@oracle.com> References: <1364147384.2052748.1570732564698.JavaMail.zimbra@u-pem.fr> <0075df55-fd45-23b8-738f-4a58fc3c6a51@oracle.com> Message-ID: <1894282541.2073694.1570743271830.JavaMail.zimbra@u-pem.fr> switch to amber-spec-experts, because it's about the binary representation of a Record in the classfile. ----- Mail original ----- > De: "Maurizio Cimadamore" > ?: "Harold David Seigel" , "amber-dev" > Envoy?: Jeudi 10 Octobre 2019 22:03:23 > Objet: Re: Class.getRecordComponent() javadoc doesn't specify its behavior if the accessor of a record component is not > present > It's the usual question: do we fail when we access things reflectively > that don't seem to be there (either fully or partially) ? Or do we > silently ignore? > > I know that we have examples of both; for instance, nestmates went the > 'throw an exception' path if a member of the nest cannot be found; but > annotations went a different path, and annotations that are not found > are simply discarded. > > One might argue that annotations are 'metadata' so less crucial than > properties such as record component-ness or nestmate-ness. But still > there's a choice. > > And, whatever we do, we should probably be consistent with any kind of > error that could popup when parsing the record component attribute, such > as illegal modifiers and such. But, I guess for missing annotations on a > record component we should be consistent with the rest of the JDK, and > just drop them on the floor. Technically a record component as no modifier, and yes this worry me a bit because it's not very future proof, we may decide to add null/non-null keywords later, that said, we can still use a new attribute (an attribute of the record component) for that. > > Maurizio R?mi From jonathan.gibbons at oracle.com Fri Oct 11 00:00:20 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 10 Oct 2019 17:00:20 -0700 Subject: sample javadoc output for records and sealed types. Message-ID: I've posted the javadoc output from some small examples of records and sealed types. Three of the examples, Point, BinaryNode and Holder, were suggested by Brian as commonly used examples. The last example, Coords, declares a sealed type with two different records as subtypes, just to show how the features can be used together. You can find the output here: 1. http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ This is output from a "simple" run of javadoc, that does not link to JDK documentation. In this version, references into java.base etc show up as unlinked monospaced text. 2. http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ This is the output from a similar run of javadoc (same examples), but this time the -linkoffline option was used so that references into java.base are linked as you would expect. In both cases, I also used the "-linksource" option, so that you can also see the original source file. Look for the link in the declaration of the type name near the top of each page. For example, click on "Foo" where you see "public record Foo", etc. You can also see the raw source files here: http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ ------ Discussion: Currently, the generated documentation consistently uses the full phrase "record components" when referencing record components. This means that some of the generated text feels a little clunky. I see that in some of the hard-written doc comments (e.g. on java.lang.Record) the phrase is shortened to just "component" when the context is obvious.? Do we want to do the same here? Are there any guidelines on the terminology? Currently, following established historical precedent, records appear in their own group on the package page, alongside individual groups for classes, interfaces, enums, exceptions, errors and annotation types.? For example, look at the docs for any recent version of java.lang: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html It may be that 7 (!!) groups is a few too many, and that maybe we should reorganize these pages a bit, perhaps moving towards a tabbed table, of the sort we use on other pages. But whether or not we do anything is out of scope for this project, and should be handled separately, as a distinct enhancement for javadoc. -- Jon From amaembo at gmail.com Fri Oct 11 03:02:49 2019 From: amaembo at gmail.com (Tagir Valeev) Date: Fri, 11 Oct 2019 10:02:49 +0700 Subject: [sealed] Sealed local classes? In-Reply-To: <6be64f8f-02ad-43fc-bbe8-0410bbd2be2b@oracle.com> References: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> <6be64f8f-02ad-43fc-bbe8-0410bbd2be2b@oracle.com> Message-ID: Hello! Sorry if this was already discussed, but what about enums extending sealed interfaces? E.g.: sealed interface X permits Foo {} enum Foo implements X { // can we do this? A {}, // and what about this? Here we have an additional subclass at runtime. Or we should explicitly declare "non-sealed enum Foo" to allow this? B, C } With best regards, Tagir Valeev. On Thu, Oct 10, 2019 at 3:46 PM Maurizio Cimadamore wrote: > > > On 10/10/2019 01:50, Brian Goetz wrote: > > Right. We already restrict anon and lambda instances of the sealed > > type. Not only can't we stably write down their types in the PS > > attribute, but even if we could, it's so easy to accidentally lose > > exhaustiveness. > > This is a very good point; if I have type T = A | B | C, but then I have > 'anonymous' Ts flying around, all switches assuming A|B|C are no longer > exhaustive. > > Maurizio > From chris.hegarty at oracle.com Fri Oct 11 08:57:13 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Fri, 11 Oct 2019 09:57:13 +0100 Subject: Draft Object Serialization Specification for records - construction/destruction In-Reply-To: References: <681EBDF4-CE6D-4B52-86B9-E079FE20417E@oracle.com> <9756631.sDmPtFT6pA@cube> <1C2C454E-384E-4F28-987E-FA362256C1B5@oracle.com> Message-ID: <2E2A26BE-BA06-4FE8-B437-0EDABFA64DFF@oracle.com> Brian, Peter, On 09/10/2019 19:52, Brian Goetz wrote: > ... > I think there is room to support the future. Here are some ways we could extract the state from a record for serialization: > A. Scrape the fields. > B. Call the field accessors. > C. Invoke the canonical deconstructor (when we have them.) > D. Invoke a serialization-specific pattern if there is one (when we support them.) > Note that in a case of `record R(...) { }`, these are all the same -- the default accessors return the field values, and the default canonical deconstructor invokes the accessors. > Clearly, if the user provides an explicit serialization member (whatever that looks like), we should use that in preference to "default" serialization; this is true for classes and records alike, it's just that the default behavior differs between classes and records. So when we get to New And Improved Serialization, D presents no migration problem; we can say "if there is a serialization pattern, use that, otherwise..." Sure, makes sense. > We can make the same argument for C, since in the absence of an explicit dtor, which you can't write now, what you'd get from an implicit dtor is the result of B. Same story: "if there is a canonical ctor, use that." Agreed. So we can effectively decouple C & D from this discussion. Great. > The real question is A vs B. One can make an argument that serialization is about raw object state, which means that field-scraping is OK. Or one can make the argument that we are trying to make serialization safer, so we should prefer the accessor (when there is one.) Most of the time, though, if there is a nontrivial accessor, all it will do is make a copy (say, if the corresponding component is an array), so going through the accessor is a bit of a wasted effort. The current wording in the draft comes from the desire to be precise on the deserializing-side, to ensure that record construction respects the object model. We may have overrotated on the serializing-side. It sounds like there is room for both A and B. The proposed draft wording ( as referenced in Peter's earlier email ), from section 1.13 "Serialization of Records" [1] is: "The serialized form of a record object is a sequence of values derived from the final instance fields of the object." This is not wrong ( remember the serialized-form is a description of the on-wire representation, not a description of how to derive the actual values ), but the word could be improved. Suggest: "The serialized form of a record object is a sequence of values derived from the record components." The other area of the proposed draft spec where this impacts ( as referenced in Peter's earlier email ), is 2.1 "The ObjectOutputStream Class? [2]: "The components of the record object are written to the stream. a. If the record object is serializable or externalizable, the record components are written, as if by invoking the `defaultWriteObject` method. ? " I think that this is ok as is. It leave room for both A and B. -Chris. [1] https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.03.html#serialization-of-records [2] http://corelibs-linux-1.ie.oracle.com/~chhegar/webrevs/sv2/record/spec/records-serialization.html#the-objectoutputstream-class From maurizio.cimadamore at oracle.com Fri Oct 11 10:48:17 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 11 Oct 2019 11:48:17 +0100 Subject: sample javadoc output for records and sealed types. In-Reply-To: References: Message-ID: <91a3b76c-bbc9-1823-f141-5a8ed40862be@oracle.com> I think the output looks very clean. On the 'sealed' part I have no objectctions. On records, what you did looks, again, very clean. The only comment I have there is that it "feels" like something is missing in the summary section... e.g. for some reason I would expect a "record components summary" there. I noted that you lifted the components to the toplevel doc, but I wondering if that's the right move. If we had specific entries for components, then we could also link e.g. the accessor to the component summary which would be, I think, cool. In other words, the treatment of JavaFX comes to mind: https://docs.oracle.com/javase/9/docs/api/javafx/scene/chart/Chart.html Also, there's a precedent: enums: https://docs.oracle.com/javase/9/docs/api/java/lang/annotation/ElementType.html Here, again, we have a summary section for all the constants. Don't get me wrong, what you have is good enough for day 1, I'm mostly trying to see how much rope we can pull. Maurizio On 11/10/2019 01:00, Jonathan Gibbons wrote: > > I've posted the javadoc output from some small examples of records and > sealed types. > > Three of the examples, Point, BinaryNode and Holder, were suggested by > Brian as > commonly used examples. The last example, Coords, declares a sealed > type with > two different records as subtypes, just to show how the features can > be used together. > > You can find the output here: > > 1. http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ > > > This is output from a "simple" run of javadoc, that does not link > to JDK documentation. > In this version, references into java.base etc show up as unlinked > monospaced text. > > 2. http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ > > This is the output from a similar run of javadoc (same examples), > but this time the > -linkoffline option was used so that references into java.base are > linked as you would expect. > > > In both cases, I also used the "-linksource" option, so that you can > also see the original > source file. Look for the link in the declaration of the type name > near the top of each page. > For example, click on "Foo" where you see "public record Foo", etc. > > You can also see the raw source files here: > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ > > ------ > > Discussion: > > Currently, the generated documentation consistently uses the full > phrase "record components" > when referencing record components. This means that some of the > generated text feels a > little clunky. I see that in some of the hard-written doc comments > (e.g. on java.lang.Record) > the phrase is shortened to just "component" when the context is > obvious.? Do we want to do > the same here? Are there any guidelines on the terminology? > > Currently, following established historical precedent, records appear > in their own group > on the package page, alongside individual groups for classes, > interfaces, enums, exceptions, > errors and annotation types.? For example, look at the docs for any > recent version of java.lang: > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html > It may be that 7 (!!) groups is a few too many, and that maybe we > should reorganize these pages > a bit, perhaps moving towards a tabbed table, of the sort we use on > other pages. But whether > or not we do anything is out of scope for this project, and should be > handled separately, as a > distinct enhancement for javadoc. > > -- Jon > > From maurizio.cimadamore at oracle.com Fri Oct 11 10:59:41 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 11 Oct 2019 03:59:41 -0700 (PDT) Subject: [sealed] Sealed local classes? In-Reply-To: References: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> <6be64f8f-02ad-43fc-bbe8-0410bbd2be2b@oracle.com> Message-ID: I think an enum declaration is 'morally final' in the sense that, while it can't really be marked with ACC_FINAL (because there might be constants which extend from it), the user cannot subclass the enum. Everything weird you can do with an enum, remains _inside_ the enum declaration bubble, which I think makes mixing enums and sealed interface pretty safe. It is also lucky that we can't say 'final enum' - meaning that I would also extend it to the other keywords - that is, you can't put sealed, non-sealed on an enum. Regarding the 'anonymous enum constant' issue you raise how is that different from: sealed interface Y permits Bar, Baz {} class Bar implements Y {} ... new Bar() {} In this case, I don't think you break exhaustiveness in the same way you do if you allow anonymous implementations of Y. Clients will be assuming that Y is either a Bar or a Baz, and the fact that some of the Bars are anonymous instance is immaterial to this. Unless I misunderstood what you were trying to say. If not, I think my reasoning here would be to: 1) allow enums to implement sealed interfaces 1b) do not allow sealed, non-sealed modifiers on an enum (e.g. do the same as with final) 2) allow anonymous enum constants inside the enums in (1) - as they can't break exhaustiveness for clients Maurizio On 11/10/2019 04:02, Tagir Valeev wrote: > Hello! > > Sorry if this was already discussed, but what about enums extending > sealed interfaces? E.g.: > > sealed interface X permits Foo {} > enum Foo implements X { // can we do this? > A {}, // and what about this? Here we have an additional subclass at > runtime. Or we should explicitly declare "non-sealed enum Foo" to > allow this? > B, > C > } > > With best regards, > Tagir Valeev. > > On Thu, Oct 10, 2019 at 3:46 PM Maurizio Cimadamore > wrote: >> >> On 10/10/2019 01:50, Brian Goetz wrote: >>> Right. We already restrict anon and lambda instances of the sealed >>> type. Not only can't we stably write down their types in the PS >>> attribute, but even if we could, it's so easy to accidentally lose >>> exhaustiveness. >> This is a very good point; if I have type T = A | B | C, but then I have >> 'anonymous' Ts flying around, all switches assuming A|B|C are no longer >> exhaustive. >> >> Maurizio >> From forax at univ-mlv.fr Fri Oct 11 13:51:38 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 11 Oct 2019 15:51:38 +0200 (CEST) Subject: [sealed] Sealed local classes? In-Reply-To: References: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> <6be64f8f-02ad-43fc-bbe8-0410bbd2be2b@oracle.com> Message-ID: <846034265.2400740.1570801898094.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Maurizio Cimadamore" > ?: "Tagir Valeev" > Cc: "amber-spec-experts" > Envoy?: Vendredi 11 Octobre 2019 12:59:41 > Objet: Re: [sealed] Sealed local classes? > I think an enum declaration is 'morally final' in the sense that, while > it can't really be marked with ACC_FINAL (because there might be > constants which extend from it), the user cannot subclass the enum. > Everything weird you can do with an enum, remains _inside_ the enum > declaration bubble, which I think makes mixing enums and sealed > interface pretty safe. It is also lucky that we can't say 'final enum' - > meaning that I would also extend it to the other keywords - that is, you > can't put sealed, non-sealed on an enum. i agree with you that you can not declared an enum final but at the same time, javac will add final automatically in the classfile of a flat enum so javac should add sealed automatically for an enum with subclasses. > > Regarding the 'anonymous enum constant' issue you raise how is that > different from: > > sealed interface Y permits Bar, Baz {} > > class Bar implements Y {} > > ... new Bar() {} > > In this case, I don't think you break exhaustiveness in the same way you > do if you allow anonymous implementations of Y. > > Clients will be assuming that Y is either a Bar or a Baz, and the fact > that some of the Bars are anonymous instance is immaterial to this. > > Unless I misunderstood what you were trying to say. If not, I think my > reasoning here would be to: > > 1) allow enums to implement sealed interfaces > 1b) do not allow sealed, non-sealed modifiers on an enum (e.g. do the > same as with final) > 2) allow anonymous enum constants inside the enums in (1) - as they > can't break exhaustiveness for clients > > Maurizio R?mi > > > On 11/10/2019 04:02, Tagir Valeev wrote: >> Hello! >> >> Sorry if this was already discussed, but what about enums extending >> sealed interfaces? E.g.: >> >> sealed interface X permits Foo {} >> enum Foo implements X { // can we do this? >> A {}, // and what about this? Here we have an additional subclass at >> runtime. Or we should explicitly declare "non-sealed enum Foo" to >> allow this? >> B, >> C >> } >> >> With best regards, >> Tagir Valeev. >> >> On Thu, Oct 10, 2019 at 3:46 PM Maurizio Cimadamore >> wrote: >>> >>> On 10/10/2019 01:50, Brian Goetz wrote: >>>> Right. We already restrict anon and lambda instances of the sealed >>>> type. Not only can't we stably write down their types in the PS >>>> attribute, but even if we could, it's so easy to accidentally lose >>>> exhaustiveness. >>> This is a very good point; if I have type T = A | B | C, but then I have >>> 'anonymous' Ts flying around, all switches assuming A|B|C are no longer >>> exhaustive. >>> >>> Maurizio From brian.goetz at oracle.com Fri Oct 11 14:07:11 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2019 10:07:11 -0400 Subject: [sealed] Sealed local classes? In-Reply-To: References: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> <6be64f8f-02ad-43fc-bbe8-0410bbd2be2b@oracle.com> Message-ID: This seems reasonable to me. So, spec consequences: - sealed, non-sealed illegal on enums - enums can implement sealed types - said permission to extend pushes down to constants, including the anonymous classes of nontrivial constants > On Oct 11, 2019, at 6:59 AM, Maurizio Cimadamore wrote: > > I think an enum declaration is 'morally final' in the sense that, while it can't really be marked with ACC_FINAL (because there might be constants which extend from it), the user cannot subclass the enum. Everything weird you can do with an enum, remains _inside_ the enum declaration bubble, which I think makes mixing enums and sealed interface pretty safe. It is also lucky that we can't say 'final enum' - meaning that I would also extend it to the other keywords - that is, you can't put sealed, non-sealed on an enum. > > Regarding the 'anonymous enum constant' issue you raise how is that different from: > > sealed interface Y permits Bar, Baz {} > > class Bar implements Y {} > > ... new Bar() {} > > In this case, I don't think you break exhaustiveness in the same way you do if you allow anonymous implementations of Y. > > Clients will be assuming that Y is either a Bar or a Baz, and the fact that some of the Bars are anonymous instance is immaterial to this. > > Unless I misunderstood what you were trying to say. If not, I think my reasoning here would be to: > > 1) allow enums to implement sealed interfaces > 1b) do not allow sealed, non-sealed modifiers on an enum (e.g. do the same as with final) > 2) allow anonymous enum constants inside the enums in (1) - as they can't break exhaustiveness for clients > > Maurizio > > > On 11/10/2019 04:02, Tagir Valeev wrote: >> Hello! >> >> Sorry if this was already discussed, but what about enums extending >> sealed interfaces? E.g.: >> >> sealed interface X permits Foo {} >> enum Foo implements X { // can we do this? >> A {}, // and what about this? Here we have an additional subclass at >> runtime. Or we should explicitly declare "non-sealed enum Foo" to >> allow this? >> B, >> C >> } >> >> With best regards, >> Tagir Valeev. >> >> On Thu, Oct 10, 2019 at 3:46 PM Maurizio Cimadamore >> wrote: >>> >>> On 10/10/2019 01:50, Brian Goetz wrote: >>>> Right. We already restrict anon and lambda instances of the sealed >>>> type. Not only can't we stably write down their types in the PS >>>> attribute, but even if we could, it's so easy to accidentally lose >>>> exhaustiveness. >>> This is a very good point; if I have type T = A | B | C, but then I have >>> 'anonymous' Ts flying around, all switches assuming A|B|C are no longer >>> exhaustive. >>> >>> Maurizio >>> From brian.goetz at oracle.com Fri Oct 11 14:11:34 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2019 07:11:34 -0700 (PDT) Subject: sample javadoc output for records and sealed types. In-Reply-To: <91a3b76c-bbc9-1823-f141-5a8ed40862be@oracle.com> References: <91a3b76c-bbc9-1823-f141-5a8ed40862be@oracle.com> Message-ID: > On records, what you did looks, again, very clean. The only comment I have there is that it "feels" like something is missing in the summary section... e.g. for some reason I would expect a "record components summary" there. I noted that you lifted the components to the toplevel doc, but I wondering if that's the right move. > > There is a ?record components? summary, but it is easy to miss ? I missed it on first read too. It is in the top section. I think it might go better if it were right below the ?public record Foo? signature, where the class doc is? From chris.hegarty at oracle.com Fri Oct 11 15:37:49 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Fri, 11 Oct 2019 16:37:49 +0100 Subject: sample javadoc output for records and sealed types. In-Reply-To: References: Message-ID: <4D799DC7-CFF7-48A6-A11D-F20FA70AD387@oracle.com> Jon, The javadoc looks great. I?m sure that this has come up already, but I cannot find it, so I?ll ask here. Should the javadoc include the fact that a record class is `final`? Or is that implied by the fact that it is a record? The reason I ask is that one can write `public final record R {}`. Will the javadoc for `R` show final? If so, then it could be a little confusing that the docs for some records may show final and others not. Maybe it just needs to be consistent one way or another. ( I found myself drawn to this question by the obvious presence of the public constructor ) -Chris. > On 11 Oct 2019, at 01:00, Jonathan Gibbons wrote: > > I've posted the javadoc output from some small examples of records and sealed types. > > Three of the examples, Point, BinaryNode and Holder, were suggested by Brian as > commonly used examples. The last example, Coords, declares a sealed type with > two different records as subtypes, just to show how the features can be used together. > > You can find the output here: > > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ > > This is output from a "simple" run of javadoc, that does not link to JDK documentation. > In this version, references into java.base etc show up as unlinked monospaced text. > > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ > > This is the output from a similar run of javadoc (same examples), but this time the > -linkoffline option was used so that references into java.base are linked as you would expect. > > > In both cases, I also used the "-linksource" option, so that you can also see the original > source file. Look for the link in the declaration of the type name near the top of each page. > For example, click on "Foo" where you see "public record Foo", etc. > > You can also see the raw source files here: > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ > ------ > > Discussion: > > Currently, the generated documentation consistently uses the full phrase "record components" > when referencing record components. This means that some of the generated text feels a > little clunky. I see that in some of the hard-written doc comments (e.g. on java.lang.Record) > the phrase is shortened to just "component" when the context is obvious. Do we want to do > the same here? Are there any guidelines on the terminology? > > Currently, following established historical precedent, records appear in their own group > on the package page, alongside individual groups for classes, interfaces, enums, exceptions, > errors and annotation types. For example, look at the docs for any recent version of java.lang: > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html > It may be that 7 (!!) groups is a few too many, and that maybe we should reorganize these pages > a bit, perhaps moving towards a tabbed table, of the sort we use on other pages. But whether > or not we do anything is out of scope for this project, and should be handled separately, as a > distinct enhancement for javadoc. > > -- Jon > > From brian.goetz at oracle.com Fri Oct 11 15:43:59 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2019 11:43:59 -0400 Subject: sample javadoc output for records and sealed types. In-Reply-To: <4D799DC7-CFF7-48A6-A11D-F20FA70AD387@oracle.com> References: <4D799DC7-CFF7-48A6-A11D-F20FA70AD387@oracle.com> Message-ID: <1113EFA3-5613-4B50-8431-B7BE6CA603F2@oracle.com> I think it would be good if the javadoc always said ?final? for records, regardless of what was in the source. > On Oct 11, 2019, at 11:37 AM, Chris Hegarty wrote: > > Jon, > > The javadoc looks great. > > I?m sure that this has come up already, but I cannot find it, so I?ll ask here. > > Should the javadoc include the fact that a record class is `final`? Or is that implied by the fact that it is a record? > > The reason I ask is that one can write `public final record R {}`. Will the javadoc for `R` show final? If so, then it could be a little confusing that the docs for some records may show final and others not. Maybe it just needs to be consistent one way or another. ( I found myself drawn to this question by the obvious presence of the public constructor ) > > -Chris. > >> On 11 Oct 2019, at 01:00, Jonathan Gibbons > wrote: >> >> I've posted the javadoc output from some small examples of records and sealed types. >> >> Three of the examples, Point, BinaryNode and Holder, were suggested by Brian as >> commonly used examples. The last example, Coords, declares a sealed type with >> two different records as subtypes, just to show how the features can be used together. >> >> You can find the output here: >> >> http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ >> >> This is output from a "simple" run of javadoc, that does not link to JDK documentation. >> In this version, references into java.base etc show up as unlinked monospaced text. >> >> http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ >> >> This is the output from a similar run of javadoc (same examples), but this time the >> -linkoffline option was used so that references into java.base are linked as you would expect. >> >> >> In both cases, I also used the "-linksource" option, so that you can also see the original >> source file. Look for the link in the declaration of the type name near the top of each page. >> For example, click on "Foo" where you see "public record Foo", etc. >> >> You can also see the raw source files here: >> http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ >> ------ >> >> Discussion: >> >> Currently, the generated documentation consistently uses the full phrase "record components" >> when referencing record components. This means that some of the generated text feels a >> little clunky. I see that in some of the hard-written doc comments (e.g. on java.lang.Record) >> the phrase is shortened to just "component" when the context is obvious. Do we want to do >> the same here? Are there any guidelines on the terminology? >> >> Currently, following established historical precedent, records appear in their own group >> on the package page, alongside individual groups for classes, interfaces, enums, exceptions, >> errors and annotation types. For example, look at the docs for any recent version of java.lang: >> https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html >> It may be that 7 (!!) groups is a few too many, and that maybe we should reorganize these pages >> a bit, perhaps moving towards a tabbed table, of the sort we use on other pages. But whether >> or not we do anything is out of scope for this project, and should be handled separately, as a >> distinct enhancement for javadoc. >> >> -- Jon >> >> > From jonathan.gibbons at oracle.com Fri Oct 11 15:47:39 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 11 Oct 2019 08:47:39 -0700 Subject: sample javadoc output for records and sealed types. In-Reply-To: <1113EFA3-5613-4B50-8431-B7BE6CA603F2@oracle.com> References: <4D799DC7-CFF7-48A6-A11D-F20FA70AD387@oracle.com> <1113EFA3-5613-4B50-8431-B7BE6CA603F2@oracle.com> Message-ID: Noted.?? But I also note we suppress always-on modifiers for other elements :-)? So I guess we choose on a case-by-case basis. FWIW, javadoc is driven by the Language Model (javax.lang.model) API, and not what is in the source code. -- Jon On 10/11/19 8:43 AM, Brian Goetz wrote: > I think it would be good if the javadoc always said ?final? for > records, regardless of what was in the source. > >> On Oct 11, 2019, at 11:37 AM, Chris Hegarty > > wrote: >> >> Jon, >> >> The javadoc looks great. >> >> I?m sure that this has come up already, but I cannot find it, so I?ll >> ask here. >> >> Should the javadoc include the fact that a record class is `final`? >> Or is that implied by the fact that it is a record? >> >> The reason I ask is that one can write `public final record R {}`. >> Will the javadoc for `R` show final? ?If so, then it could be a >> little confusing that the docs for some records may show final and >> others not. Maybe it just needs to be consistent one way or another. >> ?( I found myself drawn to this question by the obvious presence of >> the public constructor ) >> -Chris. >> >>> On 11 Oct 2019, at 01:00, Jonathan Gibbons >>> > >>> wrote: >>> >>> I've posted the javadoc output from some small examples of records >>> and sealed types. >>> >>> Three of the examples, Point, BinaryNode and Holder, were suggested >>> by Brian as >>> commonly used examples. The last example, Coords, declares a sealed >>> type with >>> two different records as subtypes, just to show how the features can >>> be used together. >>> >>> You can find the output here: >>> >>> 1. http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ >>> >>> >>> This is output from a "simple" run of javadoc, that does not >>> link to JDK documentation. >>> In this version, references into java.base etc show up as >>> unlinked monospaced text. >>> >>> 2. http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ >>> >>> This is the output from a similar run of javadoc (same >>> examples), but this time the >>> -linkoffline option was used so that references into java.base >>> are linked as you would expect. >>> >>> >>> In both cases, I also used the "-linksource" option, so that you can >>> also see the original >>> source file. Look for the link in the declaration of the type name >>> near the top of each page. >>> For example, click on "Foo" where you see "public record Foo", etc. >>> >>> You can also see the raw source files here: >>> http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ >>> >>> ------ >>> >>> Discussion: >>> >>> Currently, the generated documentation consistently uses the full >>> phrase "record components" >>> when referencing record components. This means that some of the >>> generated text feels a >>> little clunky. I see that in some of the hard-written doc comments >>> (e.g. on java.lang.Record) >>> the phrase is shortened to just "component" when the context is >>> obvious.? Do we want to do >>> the same here? Are there any guidelines on the terminology? >>> >>> Currently, following established historical precedent, records >>> appear in their own group >>> on the package page, alongside individual groups for classes, >>> interfaces, enums, exceptions, >>> errors and annotation types.? For example, look at the docs for any >>> recent version of java.lang: >>> https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html >>> It may be that 7 (!!) groups is a few too many, and that maybe we >>> should reorganize these pages >>> a bit, perhaps moving towards a tabbed table, of the sort we use on >>> other pages. But whether >>> or not we do anything is out of scope for this project, and should >>> be handled separately, as a >>> distinct enhancement for javadoc. >>> >>> -- Jon >>> >>> >> > From maurizio.cimadamore at oracle.com Fri Oct 11 16:01:05 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 11 Oct 2019 17:01:05 +0100 Subject: sample javadoc output for records and sealed types. In-Reply-To: References: <91a3b76c-bbc9-1823-f141-5a8ed40862be@oracle.com> Message-ID: <06ca3dee-85eb-e2bd-6c07-2cd4186d25cc@oracle.com> On 11/10/2019 15:11, Brian Goetz wrote: >> >> On records, what you did looks, again, very clean. The only comment I >> have there is that it "feels" like something is missing in the >> summary section... e.g. for some reason I would expect a "record >> components summary" there. I noted that you lifted the components to >> the toplevel doc, but I wondering if that's the right move. >> >> > > There is a ?record components? summary, but it is easy to miss ? I > missed it on first read too. ?It is in the top section. ?I think it > might go better if it were right below the ?public record Foo? > signature, where the class doc is? > I didn't "miss" it - I noted that - but then longed for more :-) Maurizio From joe.darcy at oracle.com Fri Oct 11 17:16:03 2019 From: joe.darcy at oracle.com (Joe Darcy) Date: Fri, 11 Oct 2019 10:16:03 -0700 Subject: Fields and methods of a record are marked MANDATED In-Reply-To: References: <477820421.1956849.1570716903273.JavaMail.zimbra@u-pem.fr> <0C47CD99-EAA3-4B6B-AAA7-0D8668E8025D@oracle.com> <4e9dbd47-8507-945f-9721-18ea3274b225@oracle.com> Message-ID: <18fdb94f-fb41-bf49-221b-192450d825c0@oracle.com> Hello, Some modifiers are implementation properties, like strictfp, native, and synchronized? -- they not part of the "interface" of the method per se, but still useful to apply and query in some circumstances. The "mandated" property can have a similar character as partially a function of the particulars of how the record was declared. The mandated information about records is used by the printing processor, javac -Xprint, to provide a more source-faithful representation of a record by eliding the mandated elements. The regression tests test/langtools/tools/javac/processing/model/element/TestRecordDesugar.java also looks at mandated vs explicit for record elements. At present, the test is only run against the source version of a record as the the information isn't (yet) available to the same degree from class file. Cheers, -Joe PS Lack of consistent mandated information around method parameters has made it difficult to address several long-standing issue in the core reflection API. On 10/10/2019 10:41 AM, Alex Buckley wrote: > Enum types are specified such that a `values` method is always > implicitly declared. (If you declare one explicitly, you have two > method declarations with override-equivalent signatures, which is an > error per JLS 8.4.) Accordingly, the corresponding method in the class > file should always be marked as mandated. Sadly we don't have room for > an ACC_MANDATED flag in `method_info`, but morally the method is > mandated and Core Reflection should expose that fact. > > Record types are specified more sensitively: a component's accessor is > implicitly declared if and only if it isn't explicitly declared. (Same > deal as the default constructor of a class.) If a component's accessor > is explicitly declared, then there's nothing more to say; if it's > implicitly declared, then it should be marked as mandated. > > I wouldn't characterize this as member descriptor v. member > implementation, because that sounds like "the signature" v. "the > body". Fundamentally, the topic at hand is component accessors, which > are non-abstract methods of non-abstract classes; for such methods of > such classes, EITHER you declare both the signature and the body (in > which case there's an explicit declaration of both signature and body) > OR you declare neither (in which case there's an implicit declaration > of both signature and body). Ordinary consumers of the record type are > happy because they can be assured that component accessors are always > declared (i.e., the compiler will always find the signature, the VM > will always link the descriptor, and the subsequent execution of the > linked method will always do something useful), while reflective > consumers of the record type are happy because they can tell whether a > component accessor (the signature and body as one undivided entity) > was declared explicitly or implicitly. You say "random", I say > "accurate". > > Alex > > On 10/10/2019 9:09 AM, Brian Goetz wrote: >> Under that interpretation, that leaves record members in a funny >> place, since a given mandated member (e.g., an accessor for a >> component) _might_ have been explicit in the source, or might not >> have been.? Should ACC_MANDATED describe the member descriptor (?spec >> mandates a member with this descriptor?) or only the implementation >> (?the source didn?t have it, but its here in the byte code?)?? In the >> latter interpretation, the presence of ACC_MANDATED on a mandated >> member would basically be random, based on implementation-of-the-day, >> which seems wrong. >> >>> On Oct 10, 2019, at 12:06 PM, Joe Darcy wrote: >>> >>> A mandated construct is one that is mandated by the specification, >>> but not explicitly declared. Constructs of that sort have been in >>> the platform since the beginning, such as default constructors. >>> ACC_MANDATED was added to the platform only more recently and has >>> some exposure through javax.lang.model. >>> >>> I recommend going forward ACC_MANDATED to be used more widely, on >>> all the mandated structures, including the values methods on enum >>> types, etc. >>> >>> Cheers, >>> >>> -Joe >>> >>> On 10/10/2019 8:50 AM, Brian Goetz wrote: >>>> We should match the behavior of methods like `Enum::values`. >>>> >>>>> On Oct 10, 2019, at 10:15 AM, Remi Forax wrote: >>>>> >>>>> Hi all, >>>>> fields and methods of a record are marked ACC_MANDATED which >>>>> contradict JLS 13.1.12 that explains that you can not use >>>>> ACC_MANDATED on field and method. >>>>> >>>>> regards, >>>>> R?mi >>>>> >> From jonathan.gibbons at oracle.com Fri Oct 11 19:25:29 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 11 Oct 2019 12:25:29 -0700 Subject: sample javadoc output for records and sealed types. In-Reply-To: <91a3b76c-bbc9-1823-f141-5a8ed40862be@oracle.com> References: <91a3b76c-bbc9-1823-f141-5a8ed40862be@oracle.com> Message-ID: <94403efe-1986-1e44-13a3-718a29b36c20@oracle.com> On 10/11/19 3:48 AM, Maurizio Cimadamore wrote: > > On records, what you did looks, again, very clean. The only comment I > have there is that it "feels" like something is missing in the summary > section... e.g. for some reason I would expect a "record components > summary" there. I noted that you lifted the components to the toplevel > doc, but I wondering if that's the right move. > I didn't deliberately "lift" it ... I just put it beside the other items documented with @param tags ;-) This code was written before RecordComponent was added. I'll take a look to see what else can be done. -- Jon From jonathan.gibbons at oracle.com Fri Oct 11 19:32:02 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 11 Oct 2019 12:32:02 -0700 Subject: sample javadoc output for records and sealed types. In-Reply-To: References: Message-ID: I've added two new examples, for a serializable record (SerializablePoint) and a serializable type with a record for a serialization proxy (SerializableProxy): the name for that one is intended to be description of the example, although admittedly, it is not a particularly good name for the functionality of the class! The sample output has been updated in place. -- Jon On 10/10/19 5:00 PM, Jonathan Gibbons wrote: > I've posted the javadoc output from some small examples of records and > sealed types. > > Three of the examples, Point, BinaryNode and Holder, were suggested by > Brian as > commonly used examples. The last example, Coords, declares a sealed > type with > two different records as subtypes, just to show how the features can > be used together. > > You can find the output here: > > 1. > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ > > > ?? This is output from a "simple" run of javadoc, that does not link to > ?? JDK documentation. > ?? In this version, references into java.base etc show up as unlinked > ?? monospaced text. > > 2. > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ > > ?? This is the output from a similar run of javadoc (same examples), > ?? but this time the > ?? -linkoffline option was used so that references into java.base are > ?? linked as you would expect. > > > In both cases, I also used the "-linksource" option, so that you can > also see the original > source file. Look for the link in the declaration of the type name > near the top of each page. > For example, click on "Foo" where you see "public record Foo", etc. > > You can also see the raw source files here: > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ > > ------ > > Discussion: > > Currently, the generated documentation consistently uses the full > phrase "record components" > when referencing record components. This means that some of the > generated text feels a > little clunky. I see that in some of the hard-written doc comments > (e.g. on java.lang.Record) > the phrase is shortened to just "component" when the context is > obvious.? Do we want to do > the same here? Are there any guidelines on the terminology? > > Currently, following established historical precedent, records appear > in their own group > on the package page, alongside individual groups for classes, > interfaces, enums, exceptions, > errors and annotation types.? For example, look at the docs for any > recent version of java.lang: > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html > > It may be that 7 (!!) groups is a few too many, and that maybe we > should reorganize these pages > a bit, perhaps moving towards a tabbed table, of the sort we use on > other pages. But whether > or not we do anything is out of scope for this project, and should be > handled separately, as a > distinct enhancement for javadoc. > > -- Jon > > From amber-spec-experts-owner at openjdk.java.net Fri Oct 11 19:36:17 2019 From: amber-spec-experts-owner at openjdk.java.net (amber-spec-experts-owner at openjdk.java.net) Date: Fri, 11 Oct 2019 19:36:17 +0000 Subject: Your message to amber-spec-experts awaits moderator approval Message-ID: Your mail to 'amber-spec-experts' with the subject Re: sample javadoc output for records and sealed types. Is being held until the list moderator can review it for approval. The reason it is being held: Post to moderated list Either the message will get posted to the list, or you will receive notification of the moderator's decision. If you would like to cancel this posting, please visit the following URL: https://mail.openjdk.java.net/mailman/confirm/amber-spec-experts/7abbcf7af3ddd262326b7c95a9e72a5ef46c4056 From forax at univ-mlv.fr Fri Oct 11 19:49:44 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 11 Oct 2019 21:49:44 +0200 (CEST) Subject: sample javadoc output for records and sealed types. In-Reply-To: References: Message-ID: <1273398846.2502101.1570823384368.JavaMail.zimbra@u-pem.fr> Hi Johnathan, as others said, i find the javadoc very clear. Minor nits, for equals: "Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. All components are compared with '=='." Nope, they are compared using equals for reference and == for primitives and the call order of the equals is not defined (for those that write equals with side effects in it) And for hashCode and toString: A line saying that the returned value may change from one execution of the VM to an other is missing. cheers, R?mi > De: "jonathan gibbons" > ?: "amber-spec-experts" > Envoy?: Vendredi 11 Octobre 2019 02:00:20 > Objet: sample javadoc output for records and sealed types. > I've posted the javadoc output from some small examples of records and sealed > types. > Three of the examples, Point, BinaryNode and Holder, were suggested by Brian as > commonly used examples. The last example, Coords, declares a sealed type with > two different records as subtypes, just to show how the features can be used > together. > You can find the output here: > 1. [ http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ > | http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ ] > This is output from a "simple" run of javadoc, that does not link to JDK > documentation. In this version, references into java.base etc show up as > unlinked monospaced text. > 2. [ > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ | > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ ] > This is the output from a similar run of javadoc (same examples), but this time > the -linkoffline option was used so that references into java.base are linked > as you would expect. > In both cases, I also used the "-linksource" option, so that you can also see > the original > source file. Look for the link in the declaration of the type name near the top > of each page. > For example, click on "Foo" where you see "public record Foo", etc. > You can also see the raw source files here: > [ http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ | > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ ] > ------ > Discussion: > Currently, the generated documentation consistently uses the full phrase "record > components" > when referencing record components. This means that some of the generated text > feels a > little clunky. I see that in some of the hard-written doc comments (e.g. on > java.lang.Record) > the phrase is shortened to just "component" when the context is obvious. Do we > want to do > the same here? Are there any guidelines on the terminology? > Currently, following established historical precedent, records appear in their > own group > on the package page, alongside individual groups for classes, interfaces, enums, > exceptions, > errors and annotation types. For example, look at the docs for any recent > version of java.lang: > [ > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html > | > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html > ] > It may be that 7 (!!) groups is a few too many, and that maybe we should > reorganize these pages > a bit, perhaps moving towards a tabbed table, of the sort we use on other pages. > But whether > or not we do anything is out of scope for this project, and should be handled > separately, as a > distinct enhancement for javadoc. > -- Jon From forax at univ-mlv.fr Fri Oct 11 20:43:49 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 11 Oct 2019 22:43:49 +0200 (CEST) Subject: Record attribute binary format Message-ID: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> It seems we have to add an access_flag for each record component because we have to mark if the record component is a varargs or not. So the format should be Record_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_record_components; { u2 component_access_flags; u2 component_name_index; u2 component_descriptor_index; u2 attribute_count; attribute_info attributes[attributes_count]; } } with the component_access_flags allowing ACC_VARARGS. R?mi From brian.goetz at oracle.com Fri Oct 11 20:57:23 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2019 16:57:23 -0400 Subject: Record attribute binary format In-Reply-To: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> References: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> Message-ID: <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> No need.? Varargs-ness is reified with the (mandated) canonical ctor. On 10/11/2019 4:43 PM, Remi Forax wrote: > It seems we have to add an access_flag for each record component because we have to mark if the record component is a varargs or not. > > So the format should be > > Record_attribute { > u2 attribute_name_index; > u4 attribute_length; > u2 number_of_record_components; > { u2 component_access_flags; > u2 component_name_index; > u2 component_descriptor_index; > u2 attribute_count; > attribute_info attributes[attributes_count]; > } > } > > with the component_access_flags allowing ACC_VARARGS. > > R?mi From john.r.rose at oracle.com Fri Oct 11 21:12:02 2019 From: john.r.rose at oracle.com (John Rose) Date: Fri, 11 Oct 2019 14:12:02 -0700 Subject: [sealed] Sealed local classes? In-Reply-To: References: Message-ID: <262CDA84-F748-4C14-BE1B-B72802465197@oracle.com> On Oct 9, 2019, at 2:26 PM, Brian Goetz wrote: > > It is allowable, though somewhat silly, to put the `final` modifier on local classes. > > From a hierarchy-protection point of view, allowing local classes to be `sealed` is also silly, as it cannot be extended from outside the method anyway, and even if it could, such types can't show up in APIs that are accessible from outside. > > From an exhaustiveness point of view, though, one can imagine having a sealed local hierarchy (sum of records) that will be switched over within the method, though one would have to work pretty hard to imagine that. > > Note that a local class cannot be a subtype of a sealed type declared outside the same method (*), since it can't be denoted in the permits clause. > > (*) unless the permits clause is inferred. Yuck. Now a mangled name would go into the PermittedSubtypes attribute. > > Proposal: ban `sealed` and `non-sealed` modifiers on _local_ classes and interfaces. I?m OK with that ban as a starting position at least. We can lift it later if we need to. It?s a little like the ban on statics: You can?t cut arbitrary class structure into an arbitrary block. From forax at univ-mlv.fr Fri Oct 11 21:19:48 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Fri, 11 Oct 2019 23:19:48 +0200 (CEST) Subject: Record attribute binary format In-Reply-To: <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> References: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> Message-ID: <1702126045.2512742.1570828788674.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Remi Forax" , "amber-spec-experts" > Envoy?: Vendredi 11 Octobre 2019 22:57:23 > Objet: Re: Record attribute binary format > No need.? Varargs-ness is reified with the (mandated) canonical ctor. hum, this looks like a hack, it means you can not just read the Record attribute, you have to crawle all the methods to find the primary constructor. and if we take a look to the past, we have added access flags to methods, fields and classes, so there is a non negligible chance that we will want to do the same to record components in the future. R?mi > > On 10/11/2019 4:43 PM, Remi Forax wrote: >> It seems we have to add an access_flag for each record component because we have >> to mark if the record component is a varargs or not. >> >> So the format should be >> >> Record_attribute { >> u2 attribute_name_index; >> u4 attribute_length; >> u2 number_of_record_components; >> { u2 component_access_flags; >> u2 component_name_index; >> u2 component_descriptor_index; >> u2 attribute_count; >> attribute_info attributes[attributes_count]; >> } >> } >> >> with the component_access_flags allowing ACC_VARARGS. >> > > R?mi From maurizio.cimadamore at oracle.com Fri Oct 11 22:50:12 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 11 Oct 2019 23:50:12 +0100 Subject: Record attribute binary format In-Reply-To: <1702126045.2512742.1570828788674.JavaMail.zimbra@u-pem.fr> References: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> <1702126045.2512742.1570828788674.JavaMail.zimbra@u-pem.fr> Message-ID: On 11/10/2019 22:19, forax at univ-mlv.fr wrote: > ----- Mail original ----- >> De: "Brian Goetz" >> ?: "Remi Forax" , "amber-spec-experts" >> Envoy?: Vendredi 11 Octobre 2019 22:57:23 >> Objet: Re: Record attribute binary format >> No need.? Varargs-ness is reified with the (mandated) canonical ctor. > hum, this looks like a hack, it means you can not just read the Record attribute, you have to crawle all the methods to find the primary constructor. It _looks_ like an hack, but I think that, after some more thinking it's actually more correct than what you are proposing. A record contains a bunch of components, the components have a name and a type. Vararg-ness? is immaterial here; both record Foo(Object[] arr) { ... } and record Bar(Object... arr) { ... } Denote the same underlying state (e.g. an Object array). The only difference between Foo and Bar is that their _construction protocol_ is different (which might also mean, in the future, that Bar will get more liberal _deconstruction_ protocols too!); but this is cleanly captured in the canonical constructor method_info. Pedagolical test: would an 'isVarargs()' predicate on the core reflection record component be acceptable? Ugh, I don't think so. Varargs is a method concept; record components are a bit ephemeral, yes, but they are definitively _not_ methods. Maurizio > > and if we take a look to the past, we have added access flags to methods, fields and classes, so there is a non negligible chance that we will want to do the same to record components in the future. > > R?mi > >> On 10/11/2019 4:43 PM, Remi Forax wrote: >>> It seems we have to add an access_flag for each record component because we have >>> to mark if the record component is a varargs or not. >>> >>> So the format should be >>> >>> Record_attribute { >>> u2 attribute_name_index; >>> u4 attribute_length; >>> u2 number_of_record_components; >>> { u2 component_access_flags; >>> u2 component_name_index; >>> u2 component_descriptor_index; >>> u2 attribute_count; >>> attribute_info attributes[attributes_count]; >>> } >>> } >>> >>> with the component_access_flags allowing ACC_VARARGS. >>> >>> R?mi From vicente.romero at oracle.com Sat Oct 12 01:36:44 2019 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 11 Oct 2019 21:36:44 -0400 Subject: Record attribute binary format In-Reply-To: References: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> <1702126045.2512742.1570828788674.JavaMail.zimbra@u-pem.fr> Message-ID: <9f3deb16-c5f8-34fc-4a61-afef0e70e720@oracle.com> On 10/11/19 6:50 PM, Maurizio Cimadamore wrote: > > On 11/10/2019 22:19, forax at univ-mlv.fr wrote: >> ----- Mail original ----- >>> De: "Brian Goetz" >>> ?: "Remi Forax" , "amber-spec-experts" >>> >>> Envoy?: Vendredi 11 Octobre 2019 22:57:23 >>> Objet: Re: Record attribute binary format >>> No need.? Varargs-ness is reified with the (mandated) canonical ctor. >> hum, this looks like a hack, it means you can not just read the >> Record attribute, you have to crawle all the methods to find the >> primary constructor. > > It _looks_ like an hack, but I think that, after some more thinking > it's actually more correct than what you are proposing. A record > contains a bunch of components, the components have a name and a type. > Vararg-ness? is immaterial here; both > > record Foo(Object[] arr) { ... } > > and > > record Bar(Object... arr) { ... } > > Denote the same underlying state (e.g. an Object array). The only > difference between Foo and Bar is that their _construction protocol_ > is different (which might also mean, in the future, that Bar will get > more liberal _deconstruction_ protocols too!); but this is cleanly > captured in the canonical constructor method_info. > > Pedagolical test: would an 'isVarargs()' predicate on the core > reflection record component be acceptable? that method as already added to j.l.r.RecordComponent, see [1], > Ugh, I don't think so. Varargs is a method concept; record components > are a bit ephemeral, yes, but they are definitively _not_ methods. > > Maurizio Vicente [1] http://hg.openjdk.java.net/amber/amber/file/df5e1c317777/src/java.base/share/classes/java/lang/reflect/RecordComponent.java#l209 > > >> >> and if we take a look to the past, we have added access flags to >> methods, fields and classes, so there is a non negligible chance that >> we will want to do the same to record components in the future. >> >> R?mi >> >>> On 10/11/2019 4:43 PM, Remi Forax wrote: >>>> It seems we have to add an access_flag for each record component >>>> because we have >>>> to mark if the record component is a varargs or not. >>>> >>>> So the format should be >>>> >>>> Record_attribute { >>>> ??? u2 attribute_name_index; >>>> ??? u4 attribute_length; >>>> ??? u2 number_of_record_components; >>>> ??? {?? u2 component_access_flags; >>>> ??????? u2 component_name_index; >>>> ??????? u2 component_descriptor_index; >>>> ??????? u2 attribute_count; >>>> ??????? attribute_info attributes[attributes_count]; >>>> ??? } >>>> } >>>> >>>> with the component_access_flags allowing ACC_VARARGS. >>>> >>>> R?mi From amaembo at gmail.com Sat Oct 12 16:53:24 2019 From: amaembo at gmail.com (Tagir Valeev) Date: Sat, 12 Oct 2019 23:53:24 +0700 Subject: [sealed] Sealed local classes? In-Reply-To: References: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> <6be64f8f-02ad-43fc-bbe8-0410bbd2be2b@oracle.com> Message-ID: Yes, I just wanted to draw attention to this detail. The current spec draft doesn't cover this case explicitly. I agree: this solution is reasonable. With best regards, Tagir Valeev. On Fri, Oct 11, 2019 at 9:07 PM Brian Goetz wrote: > > This seems reasonable to me. So, spec consequences: > > - sealed, non-sealed illegal on enums > - enums can implement sealed types > - said permission to extend pushes down to constants, including the anonymous classes of nontrivial constants > > > > > On Oct 11, 2019, at 6:59 AM, Maurizio Cimadamore wrote: > > > > I think an enum declaration is 'morally final' in the sense that, while it can't really be marked with ACC_FINAL (because there might be constants which extend from it), the user cannot subclass the enum. Everything weird you can do with an enum, remains _inside_ the enum declaration bubble, which I think makes mixing enums and sealed interface pretty safe. It is also lucky that we can't say 'final enum' - meaning that I would also extend it to the other keywords - that is, you can't put sealed, non-sealed on an enum. > > > > Regarding the 'anonymous enum constant' issue you raise how is that different from: > > > > sealed interface Y permits Bar, Baz {} > > > > class Bar implements Y {} > > > > ... new Bar() {} > > > > In this case, I don't think you break exhaustiveness in the same way you do if you allow anonymous implementations of Y. > > > > Clients will be assuming that Y is either a Bar or a Baz, and the fact that some of the Bars are anonymous instance is immaterial to this. > > > > Unless I misunderstood what you were trying to say. If not, I think my reasoning here would be to: > > > > 1) allow enums to implement sealed interfaces > > 1b) do not allow sealed, non-sealed modifiers on an enum (e.g. do the same as with final) > > 2) allow anonymous enum constants inside the enums in (1) - as they can't break exhaustiveness for clients > > > > Maurizio > > > > > > On 11/10/2019 04:02, Tagir Valeev wrote: > >> Hello! > >> > >> Sorry if this was already discussed, but what about enums extending > >> sealed interfaces? E.g.: > >> > >> sealed interface X permits Foo {} > >> enum Foo implements X { // can we do this? > >> A {}, // and what about this? Here we have an additional subclass at > >> runtime. Or we should explicitly declare "non-sealed enum Foo" to > >> allow this? > >> B, > >> C > >> } > >> > >> With best regards, > >> Tagir Valeev. > >> > >> On Thu, Oct 10, 2019 at 3:46 PM Maurizio Cimadamore > >> wrote: > >>> > >>> On 10/10/2019 01:50, Brian Goetz wrote: > >>>> Right. We already restrict anon and lambda instances of the sealed > >>>> type. Not only can't we stably write down their types in the PS > >>>> attribute, but even if we could, it's so easy to accidentally lose > >>>> exhaustiveness. > >>> This is a very good point; if I have type T = A | B | C, but then I have > >>> 'anonymous' Ts flying around, all switches assuming A|B|C are no longer > >>> exhaustive. > >>> > >>> Maurizio > >>> > From brian.goetz at oracle.com Sat Oct 12 17:15:59 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 12 Oct 2019 13:15:59 -0400 Subject: [sealed] Sealed local classes? In-Reply-To: References: <310d8787-9d5a-36cb-95b8-5a41e1b43385@oracle.com> <6be64f8f-02ad-43fc-bbe8-0410bbd2be2b@oracle.com> Message-ID: I agree its reasonable, but I don?t think the spec quite allows it yet, so we?ll put that on the list of things to be refined. > On Oct 12, 2019, at 12:53 PM, Tagir Valeev wrote: > > Yes, I just wanted to draw attention to this detail. The current spec > draft doesn't cover this case explicitly. I agree: this solution is > reasonable. > > With best regards, > Tagir Valeev. > > On Fri, Oct 11, 2019 at 9:07 PM Brian Goetz wrote: >> >> This seems reasonable to me. So, spec consequences: >> >> - sealed, non-sealed illegal on enums >> - enums can implement sealed types >> - said permission to extend pushes down to constants, including the anonymous classes of nontrivial constants >> >> >> >>> On Oct 11, 2019, at 6:59 AM, Maurizio Cimadamore wrote: >>> >>> I think an enum declaration is 'morally final' in the sense that, while it can't really be marked with ACC_FINAL (because there might be constants which extend from it), the user cannot subclass the enum. Everything weird you can do with an enum, remains _inside_ the enum declaration bubble, which I think makes mixing enums and sealed interface pretty safe. It is also lucky that we can't say 'final enum' - meaning that I would also extend it to the other keywords - that is, you can't put sealed, non-sealed on an enum. >>> >>> Regarding the 'anonymous enum constant' issue you raise how is that different from: >>> >>> sealed interface Y permits Bar, Baz {} >>> >>> class Bar implements Y {} >>> >>> ... new Bar() {} >>> >>> In this case, I don't think you break exhaustiveness in the same way you do if you allow anonymous implementations of Y. >>> >>> Clients will be assuming that Y is either a Bar or a Baz, and the fact that some of the Bars are anonymous instance is immaterial to this. >>> >>> Unless I misunderstood what you were trying to say. If not, I think my reasoning here would be to: >>> >>> 1) allow enums to implement sealed interfaces >>> 1b) do not allow sealed, non-sealed modifiers on an enum (e.g. do the same as with final) >>> 2) allow anonymous enum constants inside the enums in (1) - as they can't break exhaustiveness for clients >>> >>> Maurizio >>> >>> >>> On 11/10/2019 04:02, Tagir Valeev wrote: >>>> Hello! >>>> >>>> Sorry if this was already discussed, but what about enums extending >>>> sealed interfaces? E.g.: >>>> >>>> sealed interface X permits Foo {} >>>> enum Foo implements X { // can we do this? >>>> A {}, // and what about this? Here we have an additional subclass at >>>> runtime. Or we should explicitly declare "non-sealed enum Foo" to >>>> allow this? >>>> B, >>>> C >>>> } >>>> >>>> With best regards, >>>> Tagir Valeev. >>>> >>>> On Thu, Oct 10, 2019 at 3:46 PM Maurizio Cimadamore >>>> wrote: >>>>> >>>>> On 10/10/2019 01:50, Brian Goetz wrote: >>>>>> Right. We already restrict anon and lambda instances of the sealed >>>>>> type. Not only can't we stably write down their types in the PS >>>>>> attribute, but even if we could, it's so easy to accidentally lose >>>>>> exhaustiveness. >>>>> This is a very good point; if I have type T = A | B | C, but then I have >>>>> 'anonymous' Ts flying around, all switches assuming A|B|C are no longer >>>>> exhaustive. >>>>> >>>>> Maurizio >>>>> >> From emcmanus at google.com Sat Oct 12 17:21:57 2019 From: emcmanus at google.com (=?UTF-8?Q?=C3=89amonn_McManus?=) Date: Sat, 12 Oct 2019 10:21:57 -0700 Subject: sample javadoc output for records and sealed types. In-Reply-To: References: Message-ID: I notice that the meaningful description Returns the Cartesian x-coordinate from the Coords interface has been overridden by the less helpful generated description Returns the value of the x record component in Coords.Cartesian. Is there a way to prevent that from happening, at least when parent and child are part of the same javadoc run? On Thu, 10 Oct 2019 at 17:04, Jonathan Gibbons wrote: > I've posted the javadoc output from some small examples of records and > sealed types. > > Three of the examples, Point, BinaryNode and Holder, were suggested by > Brian as > commonly used examples. The last example, Coords, declares a sealed type > with > two different records as subtypes, just to show how the features can be > used together. > > You can find the output here: > > 1. > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ > > > This is output from a "simple" run of javadoc, that does not link to > JDK documentation. > In this version, references into java.base etc show up as unlinked > monospaced text. > > 2. > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ > > This is the output from a similar run of javadoc (same examples), > but this time the > -linkoffline option was used so that references into java.base are > linked as you would expect. > > > In both cases, I also used the "-linksource" option, so that you can > also see the original > source file. Look for the link in the declaration of the type name near > the top of each page. > For example, click on "Foo" where you see "public record Foo", etc. > > You can also see the raw source files here: > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ > > ------ > > Discussion: > > Currently, the generated documentation consistently uses the full phrase > "record components" > when referencing record components. This means that some of the > generated text feels a > little clunky. I see that in some of the hard-written doc comments (e.g. > on java.lang.Record) > the phrase is shortened to just "component" when the context is > obvious. Do we want to do > the same here? Are there any guidelines on the terminology? > > Currently, following established historical precedent, records appear in > their own group > on the package page, alongside individual groups for classes, > interfaces, enums, exceptions, > errors and annotation types. For example, look at the docs for any > recent version of java.lang: > > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html > It may be that 7 (!!) groups is a few too many, and that maybe we should > reorganize these pages > a bit, perhaps moving towards a tabbed table, of the sort we use on > other pages. But whether > or not we do anything is out of scope for this project, and should be > handled separately, as a > distinct enhancement for javadoc. > > -- Jon > > > From maurizio.cimadamore at oracle.com Sat Oct 12 20:47:07 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Sat, 12 Oct 2019 21:47:07 +0100 Subject: Record attribute binary format In-Reply-To: <9f3deb16-c5f8-34fc-4a61-afef0e70e720@oracle.com> References: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> <1702126045.2512742.1570828788674.JavaMail.zimbra@u-pem.fr> <9f3deb16-c5f8-34fc-4a61-afef0e70e720@oracle.com> Message-ID: <952e5955-2221-80d8-7126-ff9e086f50ca@oracle.com> On 12/10/2019 02:36, Vicente Romero wrote: > > > On 10/11/19 6:50 PM, Maurizio Cimadamore wrote: >> >> On 11/10/2019 22:19, forax at univ-mlv.fr wrote: >>> ----- Mail original ----- >>>> De: "Brian Goetz" >>>> ?: "Remi Forax" , "amber-spec-experts" >>>> >>>> Envoy?: Vendredi 11 Octobre 2019 22:57:23 >>>> Objet: Re: Record attribute binary format >>>> No need.? Varargs-ness is reified with the (mandated) canonical ctor. >>> hum, this looks like a hack, it means you can not just read the >>> Record attribute, you have to crawle all the methods to find the >>> primary constructor. >> >> It _looks_ like an hack, but I think that, after some more thinking >> it's actually more correct than what you are proposing. A record >> contains a bunch of components, the components have a name and a >> type. Vararg-ness? is immaterial here; both >> >> record Foo(Object[] arr) { ... } >> >> and >> >> record Bar(Object... arr) { ... } >> >> Denote the same underlying state (e.g. an Object array). The only >> difference between Foo and Bar is that their _construction protocol_ >> is different (which might also mean, in the future, that Bar will get >> more liberal _deconstruction_ protocols too!); but this is cleanly >> captured in the canonical constructor method_info. >> >> Pedagolical test: would an 'isVarargs()' predicate on the core >> reflection record component be acceptable? > > that method as already added to j.l.r.RecordComponent, see [1], The link is not working ATM, but in any case, I don't think I like that too much. This will return false always, except for, in some cases, the last record component. It's not a single method _parameter_ that is varargs. It's the whole method. In the same way, I think that reasoning of a single record component as 'varargs' is a red herring. Maurizio > > >> Ugh, I don't think so. Varargs is a method concept; record components >> are a bit ephemeral, yes, but they are definitively _not_ methods. >> >> Maurizio > > Vicente > > [1] > http://hg.openjdk.java.net/amber/amber/file/df5e1c317777/src/java.base/share/classes/java/lang/reflect/RecordComponent.java#l209 > >> >> >>> >>> and if we take a look to the past, we have added access flags to >>> methods, fields and classes, so there is a non negligible chance >>> that we will want to do the same to record components in the future. >>> >>> R?mi >>> >>>> On 10/11/2019 4:43 PM, Remi Forax wrote: >>>>> It seems we have to add an access_flag for each record component >>>>> because we have >>>>> to mark if the record component is a varargs or not. >>>>> >>>>> So the format should be >>>>> >>>>> Record_attribute { >>>>> ??? u2 attribute_name_index; >>>>> ??? u4 attribute_length; >>>>> ??? u2 number_of_record_components; >>>>> ??? {?? u2 component_access_flags; >>>>> ??????? u2 component_name_index; >>>>> ??????? u2 component_descriptor_index; >>>>> ??????? u2 attribute_count; >>>>> ??????? attribute_info attributes[attributes_count]; >>>>> ??? } >>>>> } >>>>> >>>>> with the component_access_flags allowing ACC_VARARGS. >>>>> >>>>> R?mi > From forax at univ-mlv.fr Sat Oct 12 21:17:23 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Sat, 12 Oct 2019 23:17:23 +0200 (CEST) Subject: Record attribute binary format In-Reply-To: <952e5955-2221-80d8-7126-ff9e086f50ca@oracle.com> References: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> <1702126045.2512742.1570828788674.JavaMail.zimbra@u-pem.fr> <9f3deb16-c5f8-34fc-4a61-afef0e70e720@oracle.com> <952e5955-2221-80d8-7126-ff9e086f50ca@oracle.com> Message-ID: <918633332.2661999.1570915043019.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Maurizio Cimadamore" > ?: "Vicente Romero" , "Remi Forax" , "Brian Goetz" > > Cc: "amber-spec-experts" > Envoy?: Samedi 12 Octobre 2019 22:47:07 > Objet: Re: Record attribute binary format > On 12/10/2019 02:36, Vicente Romero wrote: >> >> >> On 10/11/19 6:50 PM, Maurizio Cimadamore wrote: >>> >>> On 11/10/2019 22:19, forax at univ-mlv.fr wrote: >>>> ----- Mail original ----- >>>>> De: "Brian Goetz" >>>>> ?: "Remi Forax" , "amber-spec-experts" >>>>> >>>>> Envoy?: Vendredi 11 Octobre 2019 22:57:23 >>>>> Objet: Re: Record attribute binary format >>>>> No need.? Varargs-ness is reified with the (mandated) canonical ctor. >>>> hum, this looks like a hack, it means you can not just read the >>>> Record attribute, you have to crawle all the methods to find the >>>> primary constructor. >>> >>> It _looks_ like an hack, but I think that, after some more thinking >>> it's actually more correct than what you are proposing. A record >>> contains a bunch of components, the components have a name and a >>> type. Vararg-ness? is immaterial here; both >>> >>> record Foo(Object[] arr) { ... } >>> >>> and >>> >>> record Bar(Object... arr) { ... } >>> >>> Denote the same underlying state (e.g. an Object array). The only >>> difference between Foo and Bar is that their _construction protocol_ >>> is different (which might also mean, in the future, that Bar will get >>> more liberal _deconstruction_ protocols too!); but this is cleanly >>> captured in the canonical constructor method_info. >>> >>> Pedagolical test: would an 'isVarargs()' predicate on the core >>> reflection record component be acceptable? >> >> that method as already added to j.l.r.RecordComponent, see [1], > > The link is not working ATM, but in any case, I don't think I like that > too much. This will return false always, except for, in some cases, the > last record component. > > It's not a single method _parameter_ that is varargs. It's the whole method. > > In the same way, I think that reasoning of a single record component as > 'varargs' is a red herring. Ok, i change my mind on this :) I agree with you that currently we only have varargs methods/constructors, there is no varargs parameters. So a "..." on the type of the last record component means that the record itself is a varargs not that a peculiar record component is a varargs. But technically a varargs record only means that when constructing a record, the canonical constructor is a varargs. So the method isVarargs() should be removed from the java.lang.reflect.RecordComponent. BTW, Should java.lang.Class have a method getCanonicalRecordConstructor() ? BTW2, if in the future we need some access flags on record components, we can still add a new attribute like MethodParameters on the Record attribute, so the current binary format is Ok. > > Maurizio R?mi From maurizio.cimadamore at oracle.com Sat Oct 12 23:32:04 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Sun, 13 Oct 2019 00:32:04 +0100 Subject: Record attribute binary format In-Reply-To: <918633332.2661999.1570915043019.JavaMail.zimbra@u-pem.fr> References: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> <1702126045.2512742.1570828788674.JavaMail.zimbra@u-pem.fr> <9f3deb16-c5f8-34fc-4a61-afef0e70e720@oracle.com> <952e5955-2221-80d8-7126-ff9e086f50ca@oracle.com> <918633332.2661999.1570915043019.JavaMail.zimbra@u-pem.fr> Message-ID: <70ab5787-6b7e-acb1-67e9-b9d2350c02b1@oracle.com> On 12/10/2019 22:17, forax at univ-mlv.fr wrote: > BTW, Should java.lang.Class have a method getCanonicalRecordConstructor() ? This would be helpful, as the serialization use case already shows us that people would want to infer the signature of the canonical descriptor from the accessors return types. Which is doable, but a bit tedious to do. I was also worried, if we drop the 'isVarargs' from the component about how a client might reconstruct vararg-ness of the constructor. In the reflective lookup that's not too important, after all the runtime type of the components is the same, regardless of varargs) - but for source reflection this might be more important to reconstruct correctly - so I think it would be nice to have an official 'link' between the record/class and its canonical constructor, both in core reflection, and source reflection. Maurizio > > BTW2, if in the future we need some access flags on record components, we can still add a new attribute like MethodParameters on the Record attribute, so the current binary format is Ok. From jonathan.gibbons at oracle.com Sun Oct 13 14:58:42 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Sun, 13 Oct 2019 07:58:42 -0700 Subject: sample javadoc output for records and sealed types. In-Reply-To: <1273398846.2502101.1570823384368.JavaMail.zimbra@u-pem.fr> References: <1273398846.2502101.1570823384368.JavaMail.zimbra@u-pem.fr> Message-ID: <24e92fa2-9dab-7886-8868-2a6537164d5c@oracle.com> On 10/11/19 12:49 PM, Remi Forax wrote: > Hi Johnathan, > as others said, i find the javadoc very clear. > > Minor nits, for equals: > ? "Indicates whether some other object is "equal to" this one. The > objects are equal if the other object is of the same class and if all > the record components are equal. All components are compared with '=='." > Nope, they are compared using equals for reference and == for > primitives and the call order of the equals is not defined (for those > that write equals with side effects in it) R?mi, javadoc checks for the presence of primitives and references, and adapts the text accordingly,? In the case you are looking at, there are no references, and so the text is correct. It seems wrong to talk about using Objects.equals for references when there are none. That being said, I guess I could qualify the text by somehow including "This implemenatation..." Note the more general text, talking about '==' and Objects.equals is included in the general description in Record.equals. > > And for hashCode and toString: > ? A line saying that the returned value may change from one execution > of the VM to an other is missing. I'm presuming that is only true for hashCode, and not toString. -- Jon > > cheers, > R?mi > > ------------------------------------------------------------------------ > > *De: *"jonathan gibbons" > *?: *"amber-spec-experts" > *Envoy?: *Vendredi 11 Octobre 2019 02:00:20 > *Objet: *sample javadoc output for records and sealed types. > > I've posted the javadoc output from some small examples of records > and sealed types. > > Three of the examples, Point, BinaryNode and Holder, were > suggested by Brian as > commonly used examples. The last example, Coords, declares a > sealed type with > two different records as subtypes, just to show how the features > can be used together. > > You can find the output here: > > 1. http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ > > > This is output from a "simple" run of javadoc, that does not > link to JDK documentation. > In this version, references into java.base etc show up as > unlinked monospaced text. > > 2. http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ > > This is the output from a similar run of javadoc (same > examples), but this time the > -linkoffline option was used so that references into java.base > are linked as you would expect. > > > In both cases, I also used the "-linksource" option, so that you > can also see the original > source file. Look for the link in the declaration of the type name > near the top of each page. > For example, click on "Foo" where you see "public record Foo", etc. > > You can also see the raw source files here: > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ > > ------ > > Discussion: > > Currently, the generated documentation consistently uses the full > phrase "record components" > when referencing record components. This means that some of the > generated text feels a > little clunky. I see that in some of the hard-written doc comments > (e.g. on java.lang.Record) > the phrase is shortened to just "component" when the context is > obvious.? Do we want to do > the same here? Are there any guidelines on the terminology? > > Currently, following established historical precedent, records > appear in their own group > on the package page, alongside individual groups for classes, > interfaces, enums, exceptions, > errors and annotation types.? For example, look at the docs for > any recent version of java.lang: > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html > It may be that 7 (!!) groups is a few too many, and that maybe we > should reorganize these pages > a bit, perhaps moving towards a tabbed table, of the sort we use > on other pages. But whether > or not we do anything is out of scope for this project, and should > be handled separately, as a > distinct enhancement for javadoc. > > -- Jon > > > From jonathan.gibbons at oracle.com Sun Oct 13 15:42:46 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Sun, 13 Oct 2019 08:42:46 -0700 Subject: sample javadoc output for records and sealed types. In-Reply-To: References: Message-ID: <163820c9-5665-e916-1c0d-98787bf62a98@oracle.com> Yeah, I'd noticed that too. It's not clear to me that you always want the inherited description in preference to the generated description, although I agree that in this case it would be clearer. Note that you can always force the use of the inherited description with /** {@inheritDoc} */. -- Jon On 10/12/19 10:21 AM, ?amonn McManus wrote: > I notice that the meaningful description Returns the Cartesian > x-coordinate > ?from > the Coords interface has been overridden by the less helpful generated > description Returns the value of the x record component > ?in > Coords.Cartesian. Is there a way to prevent that from happening, at > least when parent and child are part of the same javadoc run? > > On Thu, 10 Oct 2019 at 17:04, Jonathan Gibbons > > wrote: > > I've posted the javadoc output from some small examples of records > and > sealed types. > > Three of the examples, Point, BinaryNode and Holder, were > suggested by > Brian as > commonly used examples. The last example, Coords, declares a > sealed type > with > two different records as subtypes, just to show how the features > can be > used together. > > You can find the output here: > > ?1. > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-no-link/ > > > ? ? This is output from a "simple" run of javadoc, that does not > link to > ? ? JDK documentation. > ? ? In this version, references into java.base etc show up as unlinked > ? ? monospaced text. > > ?2. > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/api-with-link/ > > ? ? This is the output from a similar run of javadoc (same examples), > ? ? but this time the > ? ? -linkoffline option was used so that references into java.base are > ? ? linked as you would expect. > > > In both cases, I also used the "-linksource" option, so that you can > also see the original > source file. Look for the link in the declaration of the type name > near > the top of each page. > For example, click on "Foo" where you see "public record Foo", etc. > > You can also see the raw source files here: > http://cr.openjdk.java.net/~jjg/amber-records-and-sealed-types/src/ > > ------ > > Discussion: > > Currently, the generated documentation consistently uses the full > phrase > "record components" > when referencing record components. This means that some of the > generated text feels a > little clunky. I see that in some of the hard-written doc comments > (e.g. > on java.lang.Record) > the phrase is shortened to just "component" when the context is > obvious.? Do we want to do > the same here? Are there any guidelines on the terminology? > > Currently, following established historical precedent, records > appear in > their own group > on the package page, alongside individual groups for classes, > interfaces, enums, exceptions, > errors and annotation types.? For example, look at the docs for any > recent version of java.lang: > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/package-summary.html > It may be that 7 (!!) groups is a few too many, and that maybe we > should > reorganize these pages > a bit, perhaps moving towards a tabbed table, of the sort we use on > other pages. But whether > or not we do anything is out of scope for this project, and should be > handled separately, as a > distinct enhancement for javadoc. > > -- Jon > > From vicente.romero at oracle.com Mon Oct 14 12:29:16 2019 From: vicente.romero at oracle.com (Vicente Romero) Date: Mon, 14 Oct 2019 08:29:16 -0400 Subject: Record attribute binary format In-Reply-To: <70ab5787-6b7e-acb1-67e9-b9d2350c02b1@oracle.com> References: <717653606.2506531.1570826629727.JavaMail.zimbra@u-pem.fr> <877febcc-63a3-1190-5f06-08c2e7d41791@oracle.com> <1702126045.2512742.1570828788674.JavaMail.zimbra@u-pem.fr> <9f3deb16-c5f8-34fc-4a61-afef0e70e720@oracle.com> <952e5955-2221-80d8-7126-ff9e086f50ca@oracle.com> <918633332.2661999.1570915043019.JavaMail.zimbra@u-pem.fr> <70ab5787-6b7e-acb1-67e9-b9d2350c02b1@oracle.com> Message-ID: <75b66957-73d6-63af-ed71-d7ec747ab1e0@oracle.com> On 10/12/19 7:32 PM, Maurizio Cimadamore wrote: > > On 12/10/2019 22:17, forax at univ-mlv.fr wrote: >> BTW, Should java.lang.Class have a method >> getCanonicalRecordConstructor() ? > > This would be helpful, as the serialization use case already shows us > that people would want to infer the signature of the canonical > descriptor from the accessors return types. Which is doable, but a bit > tedious to do. I was also worried, if we drop the 'isVarargs' from the > component about how a client might reconstruct vararg-ness of the > constructor. In the reflective lookup that's not too important, after > all the runtime type of the components is the same, regardless of > varargs) - but for source reflection this might be more important to > reconstruct correctly - so I think it would be nice to have an > official 'link' between the record/class and its canonical > constructor, both in core reflection, and source reflection. we should add all these issues to our next meeting agenda tomorrow > > Maurizio > >> >> BTW2, if in the future we need some access flags on record >> components, we can still add a new attribute like MethodParameters on >> the Record attribute, so the current binary format is Ok. Vicente From amber-spec-experts-owner at openjdk.java.net Mon Oct 14 18:36:48 2019 From: amber-spec-experts-owner at openjdk.java.net (amber-spec-experts-owner at openjdk.java.net) Date: Mon, 14 Oct 2019 18:36:48 +0000 Subject: Your message to amber-spec-experts awaits moderator approval Message-ID: Your mail to 'amber-spec-experts' with the subject Re: sample javadoc output for records and sealed types. Is being held until the list moderator can review it for approval. The reason it is being held: Post to moderated list Either the message will get posted to the list, or you will receive notification of the moderator's decision. If you would like to cancel this posting, please visit the following URL: https://mail.openjdk.java.net/mailman/confirm/amber-spec-experts/d13bdd012538712a42c59fe09296f858a6b5d4b9 From chris.hegarty at oracle.com Tue Oct 15 11:28:32 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Tue, 15 Oct 2019 12:28:32 +0100 Subject: Draft Object Serialization Specification for records - update Message-ID: Please find a link to an updated draft serialization spec for records. This version contains all comments and feedback so far. https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.04.html * Updated to reflect the new Class::getRecordComponents * For migration from a record class to a record-like class, a record may declare serialVersionUID, which is effectively ignored when local class equivalent of the specified stream class descriptor is a record class * The readResolve method is allowed, to support the use of records as serial proxies. * Section 1.13 no longer refers to the final fields, but to the record components. -Chris. From maurizio.cimadamore at oracle.com Tue Oct 15 16:10:47 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 15 Oct 2019 17:10:47 +0100 Subject: instance initializer In-Reply-To: <1830756.zWCvX6glAt@cube> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <5571324.9zj6BMyFhJ@cube> <757b649e-037d-1705-be2d-272717b5d431@oracle.com> <1830756.zWCvX6glAt@cube> Message-ID: Hi Peter, we've been thinking more about this... as it was noted in this thread, perhaps the biggest value of 'lone' instance initializers is that they contain _common_ initialization code that is replicated across _all_ constructors. Do we need this for records? Probably no, we don't - the reason being that a record is a well-behaved construct that acts as a transparent wrapper for its state, with an equally well-defined way to construct it (the canonical constructor). The way I see it, is that it is more a bug than a feature the fact that you can have 5 unrelated constructors on a record class - because one of the values behind opting for a record (vs. a class) in the first place, is to have control over the way in which record instances are created - which is in fact backed up by serialization as well (serialization guarantees that creation will always go through the canonical constructor). So I think having a constructor that doesn't delegate to the canonical constructor is potentially dangerous, as it exposes an alternate way to construct a record which is not the _blessed_ one, might skip some of the invariant checks etc. Let's say we demand that all secondary constructors starts off by delegating to the canonical constructor: this(...) If that's the case, then all initialization goes through the canonical constructor, which also means that the canonical constructor is also the code where you'd put the statements you otherwise would have put into an instance initializer. In other words, we want alternate constructors to be used as a way of providing convenience overloads, as in this case: record Point(int x, int y) { ??? Point() { this(0, 0); } } I don't think there's anything to be gain by making secondary constructors more flexible as, by doing so, we would also lose an important invariant of record construction - that all record creation flows through the canonical constructor. Therefore, I'd like to propose that: * a secondary, non-canonical constructor must always start with this(...) (the target of the delegation might be another secondary constructor, but you will eventually reach the canonical one) * instance initializers on records are banned Maurizio On 06/10/2019 17:51, Peter Levart wrote: > On Sunday, October 6, 2019 6:21:45 PM CEST Brian Goetz wrote: >>> In these scheme, canonical constructor also acts as instance initializer, >>> since it is always called from other constructors. Classical instance >>> initializer is therefore not needed any more and could be prohibited in >>> record types. >> I would agree that instance initializers in records are mostly useless, >> and keeping them around adds some complexity. Any work that can be done >> in an II could also be done in a compact ctor with about the same number >> of keystrokes: >> >> { ++instanceCount; } >> >> vs >> >> Foo { ++instanceCount; } >> >> The argument for keeping them is to minimize the number of gratuitous >> differences between records and classes. But, "it is a compile-time >> error for a record class to have an instance initializer" is a pretty >> simple spec change... and probably no one will notice. > I know that making special rules in record constructors (about being able to > access instance fields) is also increasing the number of gratuitous > differences between records and classes, but in order to ban instance > initializers, there has to be a an alternative way to specify initializing > code that is always executed. Perhaps it is enough just to suggest users to > put such code into canonical constructor and always call that constructor from > other constructors as opposed to forcing them to do that with language > constraints. > > Regards, Peter > > > From amaembo at gmail.com Fri Oct 18 09:02:26 2019 From: amaembo at gmail.com (Tagir Valeev) Date: Fri, 18 Oct 2019 16:02:26 +0700 Subject: [sealed] Sealed interface as a utility class? Message-ID: Hello! A utility class (a class that has only static members) is a ubiquitous Java pattern. They are used in JDK, common third-party libraries and applications. Usually, it's a final class. Since Java 8 (static methods were introduced in the interface) it's possible to convert a utility class to an interface. There are a number of advantages: - It cannot be instantiated, by interface definition. As a result, you don't need to create an ugly constructor like `private MyUtils() {throw new UnsupportedOperationException();}` - If you care much about code coverage, now you would have very bad times trying to cover this constructor (some people do this!). Declare it as an interface, and the problem is gone. - No need to specify `static final` on the fields -- less visual noise - No need to specify `static` on nested classes -- less visual noise - You cannot accidentally declare a non-static member: it will be a compilation error, and IDE will highlight it immediately suggesting a fix. My experience shows that people indeed sometimes mistakenly declare a non-static member in a utility class and realize this only on the first usage. This is frustrating (why I don't see the completion option? I just added this method, I know it's there! Is my IDE drunk?) and takes time to fix. - You cannot accidentally declare a non-static field or a non-static nested class. You simply cannot. Unfortunately one may implement such an interface which is not what we would like to allow. In fact, such an approach was used in early Java versions (until import static was introduced in Java 5) to use interfaces that declare only constants (this is a subset of utility classes). Now it's considered an anti-pattern to implement such an interface [1]. Having sealed classes we may declare such an interface as a sealed and provide no implementations at all, making it effectively final. Unfortunately (or not), the latest spec draft [2] explicitly disables this (9.1.4): > It is a compile-time error if a sealed interface has no permitted subtypes. This could be worked around introducing a bogus implementor inside: public sealed interface MyUtils { private final class X implements MyUtils {} // just to make a compiler happy // static members follow } This will undermine the first advantage, as the bogus class should again have the throwing constructor. However, you still have less visual noise, and you've got protection against an accidental non-static member. So we may expect that people will (ab)use this pattern. The question is: whether should we support this or not? If yes, we could lift the restriction on sealed interfaces without permits (which essentially allows creating final interfaces). We could go further and while allowing such interfaces we may disable any instance or default methods inside (as nobody could call them anyway) which would make the thing even more robust, and everybody would know that final interface is a utility class. If we don't support this, probably we should spell this out somewhere. If somebody going to write a programmer's guide to sealed classes (similar to TextBlocks one [3]), probably it's a good point to mention. A good alternative would be to invent a special syntax for utility classes like `utlity class MyUtils {}`. This adds a few restrictions: - All members are implicitly static; static modifier is allowed but not necessary - All fields are implicitly final, like in interfaces - Constructors and instance initializers are disallowed - Inheritors and instantiation is disallowed - A `utility` modifier could be obtained via reflection This would be a nice alternative, and there will be no reason to abuse other language features. With best regards, Tagir Valeev. [1] https://en.wikipedia.org/wiki/Constant_interface [2] http://cr.openjdk.java.net/~gbierman/jep360/jep360-20190830/specs/sealed-types-jls.html [3] https://cr.openjdk.java.net/~jlaskey/Strings/TextBlocksGuide_v9.html From maurizio.cimadamore at oracle.com Fri Oct 18 13:47:32 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 18 Oct 2019 14:47:32 +0100 Subject: [sealed] Sealed interface as a utility class? In-Reply-To: References: Message-ID: <184c2c34-0bad-c5fa-6443-9dc3509d03bd@oracle.com> Hi Tagir, I think think that what you are asking for is more along the lines of having "final interface" rather than sealed which permits nobody. Right? I agree that it could be worth re-examining the restriction that interfaces cannot be marked as final; I think that restriction comes from way back; if interfaces are just there to specify a contract which all implementation should adhere to, a final interface is a bit of an oxymoron. But after the recent addition to the language, the distinction between classes and interfaces has gotten quite thin: - interfaces can have default implementations - interfaces can have static methods - interfaces can have private methods So, it is conceivable that one might now want to use an interface not to specify behavior, but, more simply, to define a bad of associate static methods. In such a case, marking the interface as 'final' makes perfect sense. So, I think the question here is more whether we're philosophically ok with people using the "interface" construct in this fashion; one might argue that this is, admittedly, quite far from what language designers had in mind for interfaces in the first place; but at the same time, as you also noted, this didn't stop developers from using interfaces to define bags of constants and then having clients 'implement' them (to inherit the constants) which was eventually replaced by the more stable import static feature. Maurizio On 18/10/2019 10:02, Tagir Valeev wrote: > Hello! > > A utility class (a class that has only static members) is a ubiquitous > Java pattern. They are used in JDK, common third-party libraries and > applications. Usually, it's a final class. Since Java 8 (static > methods were introduced in the interface) it's possible to convert a > utility class to an interface. There are a number of advantages: > > - It cannot be instantiated, by interface definition. As a result, you > don't need to create an ugly constructor like `private MyUtils() > {throw new UnsupportedOperationException();}` > - If you care much about code coverage, now you would have very bad > times trying to cover this constructor (some people do this!). Declare > it as an interface, and the problem is gone. > - No need to specify `static final` on the fields -- less visual noise > - No need to specify `static` on nested classes -- less visual noise > - You cannot accidentally declare a non-static member: it will be a > compilation error, and IDE will highlight it immediately suggesting a > fix. My experience shows that people indeed sometimes mistakenly > declare a non-static member in a utility class and realize this only > on the first usage. This is frustrating (why I don't see the > completion option? I just added this method, I know it's there! Is my > IDE drunk?) and takes time to fix. > - You cannot accidentally declare a non-static field or a non-static > nested class. You simply cannot. > > Unfortunately one may implement such an interface which is not what we > would like to allow. In fact, such an approach was used in early Java > versions (until import static was introduced in Java 5) to use > interfaces that declare only constants (this is a subset of utility > classes). Now it's considered an anti-pattern to implement such an > interface [1]. > > Having sealed classes we may declare such an interface as a sealed and > provide no implementations at all, making it effectively final. > Unfortunately (or not), the latest spec draft [2] explicitly disables > this (9.1.4): > >> It is a compile-time error if a sealed interface has no permitted subtypes. > This could be worked around introducing a bogus implementor inside: > > public sealed interface MyUtils { > private final class X implements MyUtils {} // just to make a compiler happy > // static members follow > } > > This will undermine the first advantage, as the bogus class should > again have the throwing constructor. However, you still have less > visual noise, and you've got protection against an accidental > non-static member. So we may expect that people will (ab)use this > pattern. > > The question is: whether should we support this or not? If yes, we > could lift the restriction on sealed interfaces without permits (which > essentially allows creating final interfaces). We could go further and > while allowing such interfaces we may disable any instance or default > methods inside (as nobody could call them anyway) which would make the > thing even more robust, and everybody would know that final interface > is a utility class. > > If we don't support this, probably we should spell this out somewhere. > If somebody going to write a programmer's guide to sealed classes > (similar to TextBlocks one [3]), probably it's a good point to > mention. > > A good alternative would be to invent a special syntax for utility > classes like `utlity class MyUtils {}`. This adds a few restrictions: > - All members are implicitly static; static modifier is allowed but > not necessary > - All fields are implicitly final, like in interfaces > - Constructors and instance initializers are disallowed > - Inheritors and instantiation is disallowed > - A `utility` modifier could be obtained via reflection > This would be a nice alternative, and there will be no reason to abuse > other language features. > > With best regards, > Tagir Valeev. > > [1] https://en.wikipedia.org/wiki/Constant_interface > [2] http://cr.openjdk.java.net/~gbierman/jep360/jep360-20190830/specs/sealed-types-jls.html > [3] https://cr.openjdk.java.net/~jlaskey/Strings/TextBlocksGuide_v9.html From brian.goetz at oracle.com Fri Oct 18 14:16:54 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 18 Oct 2019 10:16:54 -0400 Subject: [sealed] Sealed interface as a utility class? In-Reply-To: References: Message-ID: In the ?things to tweak about interfaces? department, I would place a higher priority on aligning the restrictions on member accessibility ? right now, we can have private methods, but not private member classes (or private fields, though that?s less of a motivation.) I have mixed feelings about the proposal here. On the one hand, it is motivated by the right thoughts ? making it easy for users to follow a pattern to reliably do a common thing. On the other, I don?t particularly like ?language design by design pattern? ? it feels too roundabout. Stepping back, the proposal seems to really be about _instance control_. Both the ?singleton? and (warning, I?m gonna make up a silly word) ?nonegleton? patterns are useful, but require workarounds to implement. (Singleton requires either abuse of enums, or a private field with a public caching accessor; ?nonegleton? requires a constructor that no code is ever intended to call. These are like the current workaround for sealed types, where we can have the effect of sealed classes if the constructor is not widely accessible.) I share your distaste for code constructs that are intended to never be used, and are there entirely for their ?side effects.? Scala approaches the singleton pattern with the `object` abstraction; an `object` is a class with exactly one instance. It is a more principled approach than static members, in that everything is still an object, and `object` can implement interfaces. (Also, language support for singleton subsumes nonegleton reasonably well.) As a syntactic bonus, you don?t have to say ?static? when declaring members. Singleton objects in Scala also also play a role in the implicits story, acting as ?service providers? for things like factories. There are some items on the longer-term roadmap that may have some overlap here as well. All this said, I think there?s something missing here ? most likely, something for managing instance control of classes and interfaces alike ? but I?m not inclined to move it to the front of the queue just because sealed types are currently in play. But I think its something worth continuing to think about. > On Oct 18, 2019, at 5:02 AM, Tagir Valeev wrote: > > Hello! > > A utility class (a class that has only static members) is a ubiquitous > Java pattern. They are used in JDK, common third-party libraries and > applications. Usually, it's a final class. Since Java 8 (static > methods were introduced in the interface) it's possible to convert a > utility class to an interface. There are a number of advantages: > > - It cannot be instantiated, by interface definition. As a result, you > don't need to create an ugly constructor like `private MyUtils() > {throw new UnsupportedOperationException();}` > - If you care much about code coverage, now you would have very bad > times trying to cover this constructor (some people do this!). Declare > it as an interface, and the problem is gone. > - No need to specify `static final` on the fields -- less visual noise > - No need to specify `static` on nested classes -- less visual noise > - You cannot accidentally declare a non-static member: it will be a > compilation error, and IDE will highlight it immediately suggesting a > fix. My experience shows that people indeed sometimes mistakenly > declare a non-static member in a utility class and realize this only > on the first usage. This is frustrating (why I don't see the > completion option? I just added this method, I know it's there! Is my > IDE drunk?) and takes time to fix. > - You cannot accidentally declare a non-static field or a non-static > nested class. You simply cannot. > > Unfortunately one may implement such an interface which is not what we > would like to allow. In fact, such an approach was used in early Java > versions (until import static was introduced in Java 5) to use > interfaces that declare only constants (this is a subset of utility > classes). Now it's considered an anti-pattern to implement such an > interface [1]. > > Having sealed classes we may declare such an interface as a sealed and > provide no implementations at all, making it effectively final. > Unfortunately (or not), the latest spec draft [2] explicitly disables > this (9.1.4): > >> It is a compile-time error if a sealed interface has no permitted subtypes. > > This could be worked around introducing a bogus implementor inside: > > public sealed interface MyUtils { > private final class X implements MyUtils {} // just to make a compiler happy > // static members follow > } > > This will undermine the first advantage, as the bogus class should > again have the throwing constructor. However, you still have less > visual noise, and you've got protection against an accidental > non-static member. So we may expect that people will (ab)use this > pattern. > > The question is: whether should we support this or not? If yes, we > could lift the restriction on sealed interfaces without permits (which > essentially allows creating final interfaces). We could go further and > while allowing such interfaces we may disable any instance or default > methods inside (as nobody could call them anyway) which would make the > thing even more robust, and everybody would know that final interface > is a utility class. > > If we don't support this, probably we should spell this out somewhere. > If somebody going to write a programmer's guide to sealed classes > (similar to TextBlocks one [3]), probably it's a good point to > mention. > > A good alternative would be to invent a special syntax for utility > classes like `utlity class MyUtils {}`. This adds a few restrictions: > - All members are implicitly static; static modifier is allowed but > not necessary > - All fields are implicitly final, like in interfaces > - Constructors and instance initializers are disallowed > - Inheritors and instantiation is disallowed > - A `utility` modifier could be obtained via reflection > This would be a nice alternative, and there will be no reason to abuse > other language features. > > With best regards, > Tagir Valeev. > > [1] https://en.wikipedia.org/wiki/Constant_interface > [2] http://cr.openjdk.java.net/~gbierman/jep360/jep360-20190830/specs/sealed-types-jls.html > [3] https://cr.openjdk.java.net/~jlaskey/Strings/TextBlocksGuide_v9.html From forax at univ-mlv.fr Fri Oct 18 14:24:23 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 18 Oct 2019 16:24:23 +0200 (CEST) Subject: [sealed] Sealed interface as a utility class? In-Reply-To: References: Message-ID: <1478776234.2650310.1571408663279.JavaMail.zimbra@u-pem.fr> Tagir, there is an easy way to create a nonegleton, use a sealed interface with one implementation class and then remove that class :) R?mi ----- Mail original ----- > De: "Brian Goetz" > ?: "Tagir Valeev" > Cc: "amber-spec-experts" > Envoy?: Vendredi 18 Octobre 2019 16:16:54 > Objet: Re: [sealed] Sealed interface as a utility class? > In the ?things to tweak about interfaces? department, I would place a higher > priority on aligning the restrictions on member accessibility ? right now, we > can have private methods, but not private member classes (or private fields, > though that?s less of a motivation.) > > I have mixed feelings about the proposal here. On the one hand, it is motivated > by the right thoughts ? making it easy for users to follow a pattern to > reliably do a common thing. On the other, I don?t particularly like ?language > design by design pattern? ? it feels too roundabout. > > Stepping back, the proposal seems to really be about _instance control_. Both > the ?singleton? and (warning, I?m gonna make up a silly word) ?nonegleton? > patterns are useful, but require workarounds to implement. (Singleton requires > either abuse of enums, or a private field with a public caching accessor; > ?nonegleton? requires a constructor that no code is ever intended to call. > These are like the current workaround for sealed types, where we can have the > effect of sealed classes if the constructor is not widely accessible.) I share > your distaste for code constructs that are intended to never be used, and are > there entirely for their ?side effects.? > > Scala approaches the singleton pattern with the `object` abstraction; an > `object` is a class with exactly one instance. It is a more principled > approach than static members, in that everything is still an object, and > `object` can implement interfaces. (Also, language support for singleton > subsumes nonegleton reasonably well.) As a syntactic bonus, you don?t have to > say ?static? when declaring members. > > Singleton objects in Scala also also play a role in the implicits story, acting > as ?service providers? for things like factories. There are some items on the > longer-term roadmap that may have some overlap here as well. > > All this said, I think there?s something missing here ? most likely, something > for managing instance control of classes and interfaces alike ? but I?m not > inclined to move it to the front of the queue just because sealed types are > currently in play. But I think its something worth continuing to think about. > > >> On Oct 18, 2019, at 5:02 AM, Tagir Valeev wrote: >> >> Hello! >> >> A utility class (a class that has only static members) is a ubiquitous >> Java pattern. They are used in JDK, common third-party libraries and >> applications. Usually, it's a final class. Since Java 8 (static >> methods were introduced in the interface) it's possible to convert a >> utility class to an interface. There are a number of advantages: >> >> - It cannot be instantiated, by interface definition. As a result, you >> don't need to create an ugly constructor like `private MyUtils() >> {throw new UnsupportedOperationException();}` >> - If you care much about code coverage, now you would have very bad >> times trying to cover this constructor (some people do this!). Declare >> it as an interface, and the problem is gone. >> - No need to specify `static final` on the fields -- less visual noise >> - No need to specify `static` on nested classes -- less visual noise >> - You cannot accidentally declare a non-static member: it will be a >> compilation error, and IDE will highlight it immediately suggesting a >> fix. My experience shows that people indeed sometimes mistakenly >> declare a non-static member in a utility class and realize this only >> on the first usage. This is frustrating (why I don't see the >> completion option? I just added this method, I know it's there! Is my >> IDE drunk?) and takes time to fix. >> - You cannot accidentally declare a non-static field or a non-static >> nested class. You simply cannot. >> >> Unfortunately one may implement such an interface which is not what we >> would like to allow. In fact, such an approach was used in early Java >> versions (until import static was introduced in Java 5) to use >> interfaces that declare only constants (this is a subset of utility >> classes). Now it's considered an anti-pattern to implement such an >> interface [1]. >> >> Having sealed classes we may declare such an interface as a sealed and >> provide no implementations at all, making it effectively final. >> Unfortunately (or not), the latest spec draft [2] explicitly disables >> this (9.1.4): >> >>> It is a compile-time error if a sealed interface has no permitted subtypes. >> >> This could be worked around introducing a bogus implementor inside: >> >> public sealed interface MyUtils { >> private final class X implements MyUtils {} // just to make a compiler happy >> // static members follow >> } >> >> This will undermine the first advantage, as the bogus class should >> again have the throwing constructor. However, you still have less >> visual noise, and you've got protection against an accidental >> non-static member. So we may expect that people will (ab)use this >> pattern. >> >> The question is: whether should we support this or not? If yes, we >> could lift the restriction on sealed interfaces without permits (which >> essentially allows creating final interfaces). We could go further and >> while allowing such interfaces we may disable any instance or default >> methods inside (as nobody could call them anyway) which would make the >> thing even more robust, and everybody would know that final interface >> is a utility class. >> >> If we don't support this, probably we should spell this out somewhere. >> If somebody going to write a programmer's guide to sealed classes >> (similar to TextBlocks one [3]), probably it's a good point to >> mention. >> >> A good alternative would be to invent a special syntax for utility >> classes like `utlity class MyUtils {}`. This adds a few restrictions: >> - All members are implicitly static; static modifier is allowed but >> not necessary >> - All fields are implicitly final, like in interfaces >> - Constructors and instance initializers are disallowed >> - Inheritors and instantiation is disallowed >> - A `utility` modifier could be obtained via reflection >> This would be a nice alternative, and there will be no reason to abuse >> other language features. >> >> With best regards, >> Tagir Valeev. >> >> [1] https://en.wikipedia.org/wiki/Constant_interface >> [2] >> http://cr.openjdk.java.net/~gbierman/jep360/jep360-20190830/specs/sealed-types-jls.html > > [3] https://cr.openjdk.java.net/~jlaskey/Strings/TextBlocksGuide_v9.html From gavin.bierman at oracle.com Mon Oct 21 09:50:11 2019 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Mon, 21 Oct 2019 10:50:11 +0100 Subject: Draft JLS spec for JEP 305: Pattern matching for instanceof In-Reply-To: References: Message-ID: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> A second, and hopefully final, draft language spec for JEP 305 (Pattern matching for instanceof) is available at: http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html Apart from a small number of minor corrections, the two main changes are: 1. We are relaxing the conditions around the typing of the instanceof operator, as discussed on the EG list a little while ago. The second operand is no longer required to be a reifiable type, but we require the type of the expression can be convertible to the type by casting conversion, and that casting conversion does not make use of an unchecked narrowing reference conversion. 2. The specification for patterns will not now appear in a new chapter, but in a new section 14.30. (Sections 14.22-14.29 will remain unused for now, to allow for further language evolution.) As always, please email me any comments/thoughts/bugs. Thanks, Gavin > On 19 Sep 2019, at 10:28, Gavin Bierman wrote: > > A draft language spec for JEP 305 (Pattern Matching for instanceof) is available at: > > http://cr.openjdk.java.net/~gbierman/jep305/jep305-20190918/specs/patterns-instanceof-jls.html > > Comments are welcomed on all aspects, but I draw your attention to a couple of things that we?d like your feedback on: > > 1. The instanceof operator restricts the type to be a reifiable reference type. The spec currently keeps that restriction for type test patterns too. But should we go further, i.e. will people expect to be able to say the following (given that this *declares* a pattern variable l)? > > if (o instanceof List l) { > ? > } > > 2. We?d like to keep the possibility open for merging of multiple pattern declarations, where it makes sense. For example: > > if (a instanceof Foo f || b instanceof Foo f) { > ? // Like to be able to use f here > } > > The current spec explicitly calls out cases like these as compile-time errors, to allow for forwards compatibility if we add this feature. But what do you think of this feature? (We have textually multiple declarations of a pattern variable, but they are ?merged?, so they are really the same thing?) > > 3. [Only for spec nerds] I am proposing to add a new Chapter 16 to discuss patterns (at the moment it?s short, but we?re planning for it to grow). The existing Chapters 16-19 will be renumbered to 17-20. Will this renumbering cause problems for anyone? > > > Thanks, > Gavin From maurizio.cimadamore at oracle.com Mon Oct 21 09:57:37 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 21 Oct 2019 10:57:37 +0100 Subject: Draft JLS spec for JEP 305: Pattern matching for instanceof In-Reply-To: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> References: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> Message-ID: <3f7f3479-7af0-cfeb-0f36-cb8fc513182a@oracle.com> Hi Gavin, looks good, and I note that you also tweaked instanceof to use a "bi-modal" semantics - e.g. instanceof Type | Pattern. On that note, I find that the section which speaks about 'type instance of' could use same cleanup you did on patterns: " If a cast of the /RelationalExpression/ to the /ReferenceType/ would be rejected as a compile-time error (15.16 ), then the |instanceof| expression likewise produces a compile-time error. In such a situation, the result of the |instanceof| expression could never be true. If the casting conversion of the /RelationalExpression/ to the /ReferenceType/ makes use of a narrowing reference conversion which is unchecked (5.1.6.2 ), then a compile-time error occurs. " The text here looks a bit redundant, and similar to what you had in the previous version of the spec. Perhaps you could use same cleanups as what you did in 14.30.2 (which, btw, looks great!) Maurizio On 21/10/2019 10:50, Gavin Bierman wrote: > A second, and hopefully final, draft language spec for JEP 305 (Pattern matching for instanceof) is available at: > > http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html > > Apart from a small number of minor corrections, the two main changes are: > > 1. We are relaxing the conditions around the typing of the instanceof operator, as discussed on the EG list a little while ago. The second operand is no longer required to be a reifiable type, but we require the type of the expression can be convertible to the type by casting conversion, and that casting conversion does not make use of an unchecked narrowing reference conversion. > > 2. The specification for patterns will not now appear in a new chapter, but in a new section 14.30. (Sections 14.22-14.29 will remain unused for now, to allow for further language evolution.) > > As always, please email me any comments/thoughts/bugs. > > Thanks, > Gavin > >> On 19 Sep 2019, at 10:28, Gavin Bierman wrote: >> >> A draft language spec for JEP 305 (Pattern Matching for instanceof) is available at: >> >> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20190918/specs/patterns-instanceof-jls.html >> >> Comments are welcomed on all aspects, but I draw your attention to a couple of things that we?d like your feedback on: >> >> 1. The instanceof operator restricts the type to be a reifiable reference type. The spec currently keeps that restriction for type test patterns too. But should we go further, i.e. will people expect to be able to say the following (given that this *declares* a pattern variable l)? >> >> if (o instanceof List l) { >> ? >> } >> >> 2. We?d like to keep the possibility open for merging of multiple pattern declarations, where it makes sense. For example: >> >> if (a instanceof Foo f || b instanceof Foo f) { >> ? // Like to be able to use f here >> } >> >> The current spec explicitly calls out cases like these as compile-time errors, to allow for forwards compatibility if we add this feature. But what do you think of this feature? (We have textually multiple declarations of a pattern variable, but they are ?merged?, so they are really the same thing?) >> >> 3. [Only for spec nerds] I am proposing to add a new Chapter 16 to discuss patterns (at the moment it?s short, but we?re planning for it to grow). The existing Chapters 16-19 will be renumbered to 17-20. Will this renumbering cause problems for anyone? >> >> >> Thanks, >> Gavin From gavin.bierman at oracle.com Mon Oct 21 11:22:42 2019 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Mon, 21 Oct 2019 12:22:42 +0100 Subject: New candidate JEP: 361: Switch Expressions (Standard) In-Reply-To: <7E8C18C5-726B-4F2C-9F3B-AC386CC97B82@oracle.com> References: <20190925223215.EDE103084E1@eggemoggin.niobe.net> <7E8C18C5-726B-4F2C-9F3B-AC386CC97B82@oracle.com> Message-ID: Just a gentle reminder if you have any feedback based on your experience with using this feature. Gavin > On 27 Sep 2019, at 17:45, Gavin Bierman wrote: > > Please note that we are considering making this a permanent feature, so this is your last chance to provide substantive feedback based on any new experience you may have had with this feature. > > A new, draft language spec for JEP 361 (Switch Expressions) is available at: > > http://cr.openjdk.java.net/~gbierman/jep361/jep361-20190927/specs/switch-expressions-jls.html > > This is identical to the version made available for JEP354, apart from some cosmetic changes around terminology following some feedback. > > [For spec nerds: The primary change is that what was previously called a "switch labeled rule" is now called, more simply, a "switch rule?. ?Switch labeled expression? is now a ?switch rule expression?, ?switch labeled block? is now a ?switch rule block? and a ?switch labeled throw statement? is now a ?switch rule throw statement?.] > > All feedback welcomed! > Gavin > >> On 25 Sep 2019, at 23:32, mark.reinhold at oracle.com wrote: >> >> https://openjdk.java.net/jeps/361 >> >> - Mark > From gavin.bierman at oracle.com Mon Oct 21 12:02:23 2019 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Mon, 21 Oct 2019 13:02:23 +0100 Subject: Draft JLS spec for JEP 305: Pattern matching for instanceof In-Reply-To: <3f7f3479-7af0-cfeb-0f36-cb8fc513182a@oracle.com> References: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> <3f7f3479-7af0-cfeb-0f36-cb8fc513182a@oracle.com> Message-ID: <2D62B016-0B07-4D20-A5C8-7A432ADABC5C@oracle.com> Thanks Maurizio. I have tweaked the two definitions to be more clearly aligned. Gavin > On 21 Oct 2019, at 10:57, Maurizio Cimadamore wrote: > > Hi Gavin, > looks good, and I note that you also tweaked instanceof to use a "bi-modal" semantics - e.g. instanceof Type | Pattern. > > On that note, I find that the section which speaks about 'type instance of' could use same cleanup you did on patterns: > > " > > If a cast of the RelationalExpression to the ReferenceType would be rejected as a compile-time error (15.16 ), then the instanceof expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true. > > If the casting conversion of the RelationalExpression to the ReferenceType makes use of a narrowing reference conversion which is unchecked (5.1.6.2 ), then a compile-time error occurs. > " > > The text here looks a bit redundant, and similar to what you had in the previous version of the spec. Perhaps you could use same cleanups as what you did in 14.30.2 (which, btw, looks great!) > > Maurizio > > > > On 21/10/2019 10:50, Gavin Bierman wrote: >> A second, and hopefully final, draft language spec for JEP 305 (Pattern matching for instanceof) is available at: >> >> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html >> >> Apart from a small number of minor corrections, the two main changes are: >> >> 1. We are relaxing the conditions around the typing of the instanceof operator, as discussed on the EG list a little while ago. The second operand is no longer required to be a reifiable type, but we require the type of the expression can be convertible to the type by casting conversion, and that casting conversion does not make use of an unchecked narrowing reference conversion. >> >> 2. The specification for patterns will not now appear in a new chapter, but in a new section 14.30. (Sections 14.22-14.29 will remain unused for now, to allow for further language evolution.) >> >> As always, please email me any comments/thoughts/bugs. >> >> Thanks, >> Gavin >> >>> On 19 Sep 2019, at 10:28, Gavin Bierman wrote: >>> >>> A draft language spec for JEP 305 (Pattern Matching for instanceof) is available at: >>> >>> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20190918/specs/patterns-instanceof-jls.html >>> >>> Comments are welcomed on all aspects, but I draw your attention to a couple of things that we?d like your feedback on: >>> >>> 1. The instanceof operator restricts the type to be a reifiable reference type. The spec currently keeps that restriction for type test patterns too. But should we go further, i.e. will people expect to be able to say the following (given that this *declares* a pattern variable l)? >>> >>> if (o instanceof List l) { >>> ? >>> } >>> >>> 2. We?d like to keep the possibility open for merging of multiple pattern declarations, where it makes sense. For example: >>> >>> if (a instanceof Foo f || b instanceof Foo f) { >>> ? // Like to be able to use f here >>> } >>> >>> The current spec explicitly calls out cases like these as compile-time errors, to allow for forwards compatibility if we add this feature. But what do you think of this feature? (We have textually multiple declarations of a pattern variable, but they are ?merged?, so they are really the same thing?) >>> >>> 3. [Only for spec nerds] I am proposing to add a new Chapter 16 to discuss patterns (at the moment it?s short, but we?re planning for it to grow). The existing Chapters 16-19 will be renumbered to 17-20. Will this renumbering cause problems for anyone? >>> >>> >>> Thanks, >>> Gavin From maurizio.cimadamore at oracle.com Mon Oct 21 12:13:58 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 21 Oct 2019 13:13:58 +0100 Subject: Draft JLS spec for JEP 305: Pattern matching for instanceof In-Reply-To: <2D62B016-0B07-4D20-A5C8-7A432ADABC5C@oracle.com> References: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> <3f7f3479-7af0-cfeb-0f36-cb8fc513182a@oracle.com> <2D62B016-0B07-4D20-A5C8-7A432ADABC5C@oracle.com> Message-ID: <0a34cbd6-eb99-c5ac-93fd-a7d99759743d@oracle.com> Looks good, thanks Maurizio On 21/10/2019 13:02, Gavin Bierman wrote: > Thanks Maurizio. I have tweaked the two definitions to be more clearly > aligned. > > Gavin > >> On 21 Oct 2019, at 10:57, Maurizio Cimadamore >> > > wrote: >> >> Hi Gavin, >> looks good, and I note that you also tweaked instanceof to use a >> "bi-modal" semantics - e.g. instanceof Type | Pattern. >> >> On that note, I find that the section which speaks about 'type >> instance of' could use same cleanup you did on patterns: >> >> " >> >> If a cast of the /RelationalExpression/ to the /ReferenceType/ would >> be rejected as a compile-time error (15.16 >> ), >> then the |instanceof| expression likewise produces a compile-time >> error. In such a situation, the result of the |instanceof| expression >> could never be true. >> >> If the casting conversion of the /RelationalExpression/ to the >> /ReferenceType/ makes use of a narrowing reference conversion which >> is unchecked (5.1.6.2 >> ), >> then a compile-time error occurs. >> " >> >> The text here looks a bit redundant, and similar to what you had in >> the previous version of the spec. Perhaps you could use same cleanups >> as what you did in 14.30.2 (which, btw, looks great!) >> >> Maurizio >> >> >> On 21/10/2019 10:50, Gavin Bierman wrote: >>> A second, and hopefully final, draft language spec for JEP 305 (Pattern matching for instanceof) is available at: >>> >>> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html >>> >>> Apart from a small number of minor corrections, the two main changes are: >>> >>> 1. We are relaxing the conditions around the typing of the instanceof operator, as discussed on the EG list a little while ago. The second operand is no longer required to be a reifiable type, but we require the type of the expression can be convertible to the type by casting conversion, and that casting conversion does not make use of an unchecked narrowing reference conversion. >>> >>> 2. The specification for patterns will not now appear in a new chapter, but in a new section 14.30. (Sections 14.22-14.29 will remain unused for now, to allow for further language evolution.) >>> >>> As always, please email me any comments/thoughts/bugs. >>> >>> Thanks, >>> Gavin >>> >>>> On 19 Sep 2019, at 10:28, Gavin Bierman wrote: >>>> >>>> A draft language spec for JEP 305 (Pattern Matching for instanceof) is available at: >>>> >>>> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20190918/specs/patterns-instanceof-jls.html >>>> >>>> Comments are welcomed on all aspects, but I draw your attention to a couple of things that we?d like your feedback on: >>>> >>>> 1. The instanceof operator restricts the type to be a reifiable reference type. The spec currently keeps that restriction for type test patterns too. But should we go further, i.e. will people expect to be able to say the following (given that this *declares* a pattern variable l)? >>>> >>>> if (o instanceof List l) { >>>> ? >>>> } >>>> >>>> 2. We?d like to keep the possibility open for merging of multiple pattern declarations, where it makes sense. For example: >>>> >>>> if (a instanceof Foo f || b instanceof Foo f) { >>>> ? // Like to be able to use f here >>>> } >>>> >>>> The current spec explicitly calls out cases like these as compile-time errors, to allow for forwards compatibility if we add this feature. But what do you think of this feature? (We have textually multiple declarations of a pattern variable, but they are ?merged?, so they are really the same thing?) >>>> >>>> 3. [Only for spec nerds] I am proposing to add a new Chapter 16 to discuss patterns (at the moment it?s short, but we?re planning for it to grow). The existing Chapters 16-19 will be renumbered to 17-20. Will this renumbering cause problems for anyone? >>>> >>>> >>>> Thanks, >>>> Gavin > From chris.hegarty at oracle.com Mon Oct 21 14:49:30 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Mon, 21 Oct 2019 15:49:30 +0100 Subject: Draft JLS spec for JEP 305: Pattern matching for instanceof In-Reply-To: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> References: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> Message-ID: > On 21 Oct 2019, at 10:50, Gavin Bierman wrote: > > A second, and hopefully final, draft language spec for JEP 305 (Pattern matching for instanceof) is available at: > > http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html While proofreading, I came across a minor issue in 15.20.2: "? The expression RelationalExpression is compatible with the type ReferenceType if (i) RelationalExpression can be converted to type ReferenceType by casting conversion (5.5), and (ii) the casting conversion does not make use of a narrowing reference conversion which is unchecked (5.1.6.2). If ReferenceType is not compatible with ReferenceType then a compile-time error occurs." Should be: If *RelationalExpression* is not compatible with ReferenceType then a compile-time error occurs. -Chris. From fredt at users.sourceforge.net Mon Oct 21 14:53:49 2019 From: fredt at users.sourceforge.net (Fred Toussi) Date: Mon, 21 Oct 2019 15:53:49 +0100 Subject: New candidate JEP: 361: Switch Expressions (Standard) In-Reply-To: References: <20190925223215.EDE103084E1@eggemoggin.niobe.net> <7E8C18C5-726B-4F2C-9F3B-AC386CC97B82@oracle.com> Message-ID: <57fc14df-6d9c-49d2-8101-51953f921865@www.fastmail.com> Typos: The spac still uses SwitchLabeledRule where it defines the new production. The example with switch (day) implies we can use both the comma and the colon as case separators. I wote to the amber-spec-observers last October (https://mail.openjdk.java.net/pipermail/amber-spec-observers/2018-October/000907.html), but got no reply to the substance of my concerns. To avoid extensive changes to existing apps, and to reduce developer confusion with multiple colon and comma separators (which is evident in the aforementioned mixed-up example given in the spec document) , I proposed: 1. Adding a keyword to the start of the switch _statement_ to indicate "break" will be automatic at the end of each case. I suggested "new switch(val) {", but "switch break(va l) {" is a probably a better alternative. No change to the usage of the colon is required. 2. Continued usage of colon for switch expression cases, with the use of the proposed arrow "->" and "yield" to return expression values. regards Fred Toussi On Mon, Oct 21, 2019, at 12:22, Gavin Bierman wrote: > Just a gentle reminder if you have any feedback based on your > experience with using this feature. > > Gavin > > > On 27 Sep 2019, at 17:45, Gavin Bierman wrote: > > > > Please note that we are considering making this a permanent feature, so this is your last chance to provide substantive feedback based on any new experience you may have had with this feature. > > > > A new, draft language spec for JEP 361 (Switch Expressions) is available at: > > > > http://cr.openjdk.java.net/~gbierman/jep361/jep361-20190927/specs/switch-expressions-jls.html > > > > This is identical to the version made available for JEP354, apart from some cosmetic changes around terminology following some feedback. > > > > [For spec nerds: The primary change is that what was previously called a "switch labeled rule" is now called, more simply, a "switch rule?. ?Switch labeled expression? is now a ?switch rule expression?, ?switch labeled block? is now a ?switch rule block? and a ?switch labeled throw statement? is now a ?switch rule throw statement?.] > > > > All feedback welcomed! > > Gavin > > > >> On 25 Sep 2019, at 23:32, mark.reinhold at oracle.com wrote: > >> > >> https://openjdk.java.net/jeps/361 > >> > >> - Mark > > > > From gavin.bierman at oracle.com Mon Oct 21 15:26:07 2019 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Mon, 21 Oct 2019 16:26:07 +0100 Subject: New candidate JEP: 361: Switch Expressions (Standard) In-Reply-To: <57fc14df-6d9c-49d2-8101-51953f921865@www.fastmail.com> References: <20190925223215.EDE103084E1@eggemoggin.niobe.net> <7E8C18C5-726B-4F2C-9F3B-AC386CC97B82@oracle.com> <57fc14df-6d9c-49d2-8101-51953f921865@www.fastmail.com> Message-ID: > On 21 Oct 2019, at 15:53, Fred Toussi wrote: > > Typos: > > The spac still uses SwitchLabeledRule where it defines the new production. Thank you. I?ll fix that. > > The example with switch (day) implies we can use both the comma and the colon as case separators. Yes, that is right, and I recall some discussion on this. We think people will move to the comma form in time. > > I wote to the amber-spec-observers last October (https://mail.openjdk.java.net/pipermail/amber-spec-observers/2018-October/000907.html), but got no reply to the substance of my concerns. > > To avoid extensive changes to existing apps, and to reduce developer confusion with multiple colon and comma separators (which is evident in the aforementioned mixed-up example given in the spec document) , I proposed: > > 1. Adding a keyword to the start of the switch _statement_ to indicate "break" will be automatic at the end of each case. I suggested "new switch(val) {", but "switch break(va l) {" is a probably a better alternative. No change to the usage of the colon is required. > > 2. Continued usage of colon for switch expression cases, with the use of the proposed arrow "->" and "yield" to return expression values. I was asking for experience of using the feature, rather than requests to reopen the design. Actually Brian has addressed this before - we had a strong design goal to *not* introduce a new switch form, but to try to evolve the existing one. Of course, evolving a feature comes with a cost, which is that some code will have evolved and some might not. However, IDEs will probably help here. Do you have experience that suggests otherwise? Thanks, Gavin From fredt at users.sourceforge.net Mon Oct 21 16:47:54 2019 From: fredt at users.sourceforge.net (Fred Toussi) Date: Mon, 21 Oct 2019 17:47:54 +0100 Subject: New candidate JEP: 361: Switch Expressions (Standard) In-Reply-To: References: <20190925223215.EDE103084E1@eggemoggin.niobe.net> <7E8C18C5-726B-4F2C-9F3B-AC386CC97B82@oracle.com> <57fc14df-6d9c-49d2-8101-51953f921865@www.fastmail.com> Message-ID: <1a1edcb0-85da-458b-aed8-4ce26a06861c@www.fastmail.com> Thanks, You asked for experience of using the feature. I attempted it previously and noticed all the colons needed changing to two different symbols in order to factor out the "break" usage. As for IDE's, they do not solve the extensive version control diffs caused by converting huge switch statements. Eveloving the switch form is a good idea. What I proposed looks more like an evolution of the traditional switch, as code will have fewer visible changes than with the current JEP 361 syntax. If the colon is retained as the case separator, the additions such as the option of qualifiying the switch with "break" and the use of the arrow and "yield" to return values just serve the purpose exactly at the point of use. Regards Fred On Mon, Oct 21, 2019, at 16:26, Gavin Bierman wrote: > > > > On 21 Oct 2019, at 15:53, Fred Toussi wrote: > > > > Typos: > > > > The spac still uses SwitchLabeledRule where it defines the new production. > > Thank you. I?ll fix that. > > > > > The example with switch (day) implies we can use both the comma and the colon as case separators. > > Yes, that is right, and I recall some discussion on this. We think > people will move to the comma form in time. > > > > > I wote to the amber-spec-observers last October (https://mail.openjdk.java.net/pipermail/amber-spec-observers/2018-October/000907.html), but got no reply to the substance of my concerns. > > > > To avoid extensive changes to existing apps, and to reduce developer confusion with multiple colon and comma separators (which is evident in the aforementioned mixed-up example given in the spec document) , I proposed: > > > > 1. Adding a keyword to the start of the switch _statement_ to indicate "break" will be automatic at the end of each case. I suggested "new switch(val) {", but "switch break(va l) {" is a probably a better alternative. No change to the usage of the colon is required. > > > > 2. Continued usage of colon for switch expression cases, with the use of the proposed arrow "->" and "yield" to return expression values. > > I was asking for experience of using the feature, rather than requests > to reopen the design. Actually Brian has addressed this before - we had > a strong design goal to *not* introduce a new switch form, but to try > to evolve the existing one. Of course, evolving a feature comes with a > cost, which is that some code will have evolved and some might not. > However, IDEs will probably help here. Do you have experience that > suggests otherwise? > > Thanks, > Gavin From forax at univ-mlv.fr Mon Oct 21 17:03:10 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 21 Oct 2019 19:03:10 +0200 (CEST) Subject: Draft JLS spec for JEP 305: Pattern matching for instanceof In-Reply-To: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> References: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> Message-ID: <567606180.421662.1571677390932.JavaMail.zimbra@u-pem.fr> 14.30.3 is weird to me, why use the cast operation that doesn't raise an exception instead of instanceof granting the null case is handled before ? R?mi > De: "Gavin Bierman" > ?: "amber-spec-experts" > Cc: "amber-dev" > Envoy?: Lundi 21 Octobre 2019 11:50:11 > Objet: Draft JLS spec for JEP 305: Pattern matching for instanceof > A second, and hopefully final, draft language spec for JEP 305 (Pattern matching > for instanceof) is available at: > [ > http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html > | > http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html > ] > Apart from a small number of minor corrections, the two main changes are: > 1. We are relaxing the conditions around the typing of the instanceof operator, > as discussed on the EG list a little while ago. The second operand is no longer > required to be a reifiable type, but we require the type of the expression can > be convertible to the type by casting conversion, and that casting conversion > does not make use of an unchecked narrowing reference conversion. > 2. The specification for patterns will not now appear in a new chapter, but in a > new section 14.30. (Sections 14.22-14.29 will remain unused for now, to allow > for further language evolution.) > As always, please email me any comments/thoughts/bugs. > Thanks, > Gavin >> On 19 Sep 2019, at 10:28, Gavin Bierman < [ mailto:gavin.bierman at oracle.com | >> gavin.bierman at oracle.com ] > wrote: >> A draft language spec for JEP 305 (Pattern Matching for instanceof) is available >> at: >> [ >> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20190918/specs/patterns-instanceof-jls.html >> | >> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20190918/specs/patterns-instanceof-jls.html >> ] >> Comments are welcomed on all aspects, but I draw your attention to a couple of >> things that we?d like your feedback on: >> 1. The instanceof operator restricts the type to be a reifiable reference type. >> The spec currently keeps that restriction for type test patterns too. But >> should we go further, i.e. will people expect to be able to say the following >> (given that this *declares* a pattern variable l)? >>> if (o instanceof List l) { >>> ? >>> } >> 2. We?d like to keep the possibility open for merging of multiple pattern >> declarations, where it makes sense. For example: >>> if (a instanceof Foo f || b instanceof Foo f) { >>> ? // Like to be able to use f here >>> } >> The current spec explicitly calls out cases like these as compile-time errors, >> to allow for forwards compatibility if we add this feature. But what do you >> think of this feature? (We have textually multiple declarations of a pattern >> variable, but they are ?merged?, so they are really the same thing?) >> 3. [Only for spec nerds] I am proposing to add a new Chapter 16 to discuss >> patterns (at the moment it?s short, but we?re planning for it to grow). The >> existing Chapters 16-19 will be renumbered to 17-20. Will this renumbering >> cause problems for anyone? >> Thanks, >> Gavin From gavin.bierman at oracle.com Mon Oct 21 19:26:03 2019 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Mon, 21 Oct 2019 20:26:03 +0100 Subject: New candidate JEP: 361: Switch Expressions (Standard) In-Reply-To: References: <20190925223215.EDE103084E1@eggemoggin.niobe.net> <7E8C18C5-726B-4F2C-9F3B-AC386CC97B82@oracle.com> <57fc14df-6d9c-49d2-8101-51953f921865@www.fastmail.com> Message-ID: <2C96450B-B273-4C79-914C-C99FF0CF1F4F@oracle.com> > On 21 Oct 2019, at 16:26, Gavin Bierman wrote: > > > >> On 21 Oct 2019, at 15:53, Fred Toussi wrote: >> >> Typos: >> >> The spac still uses SwitchLabeledRule where it defines the new production. > > Thank you. I?ll fix that. I?ve fixed that small typo in place. http://cr.openjdk.java.net/~gbierman/jep361/jep361-20190927/specs/switch-expressions-jls.html Thanks, Gavin From peter.levart at gmail.com Tue Oct 22 08:57:42 2019 From: peter.levart at gmail.com (Peter Levart) Date: Tue, 22 Oct 2019 10:57:42 +0200 Subject: Draft Object Serialization Specification for records - update In-Reply-To: References: Message-ID: Hi Chris, On 10/15/19 1:28 PM, Chris Hegarty wrote: > Please find a link to an updated draft serialization spec for records. > This version contains all comments and feedback so far. > > https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.04.html > > * Updated to reflect the new Class::getRecordComponents > * For migration from a record class to a record-like class, a record may declare serialVersionUID, which is effectively ignored when local class equivalent of the specified stream class descriptor is a record class I don't see this in the text. Specifically in 1.13. the text says: "Any serialPersistentFields or serialVersionUID field declarations are also ignored -- all record classes have a fixed serialVersionUID of 0L." And in 4.6. it says: "The serialVersionUID for dynamic proxy classes, enum types, and record classes, is always the value 0L." Also the implementation of records serialization proposed on core-libs-dev by Vincente is alligned with this text. I note that enums took an approach where their serialVersionUID is always 0L, but their serialization format is also very different than that of any enum-like class. Cross-serialization compatibility between enum-like class and enum was not a goal then. If records vs. record-like classes have a goal of Cross-serialization compatibility, then explicit serialVersionUID static final field on records must be respected during serialization, but can be ignored during deserialization to enable later removing of the static field when migration from record-like class is finally complete. Regards, Peter From chris.hegarty at oracle.com Tue Oct 22 12:34:46 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Tue, 22 Oct 2019 13:34:46 +0100 Subject: Draft Object Serialization Specification for records - update In-Reply-To: References: Message-ID: <1BA68EB1-6CB0-4727-8986-BA50692884E0@oracle.com> Hi Peter, Thanks for following up on this. > On 22 Oct 2019, at 09:57, Peter Levart wrote: > > Hi Chris, > > On 10/15/19 1:28 PM, Chris Hegarty wrote: >> Please find a link to an updated draft serialization spec for records. >> This version contains all comments and feedback so far. >> >> https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.04.html >> >> * Updated to reflect the new Class::getRecordComponents >> * For migration from a record class to a record-like class, a record may declare serialVersionUID, which is effectively ignored when local class equivalent of the specified stream class descriptor is a record class > I don't see this in the text. Specifically in 1.13. the text says: > > "Any serialPersistentFields or serialVersionUID field declarations are also ignored -- all record classes have a fixed serialVersionUID of 0L." > > And in 4.6. it says: > > "The serialVersionUID for dynamic proxy classes, enum types, and record classes, is always the value 0L." > > Also the implementation of records serialization proposed on core-libs-dev by Vincente is alligned with this text. > > > I note that enums took an approach where their serialVersionUID is always 0L, but their serialization format is also very different than that of any enum-like class. Cross-serialization compatibility between enum-like class and enum was not a goal then. > > If records vs. record-like classes have a goal of Cross-serialization compatibility, then explicit serialVersionUID static final field on records must be respected during serialization, but can be ignored during deserialization to enable later removing of the static field when migration from record-like class is finally complete. Apologies ( the change never made it through ), you are of course correct. Here is an updated version of the spec with sections 1.13 ?Serialization of Records?, and section 4.6 ?Stream Unique Identifiers? updated: https://cr.openjdk.java.net/~chegar/records/spec/records-serialization.05.html The implementation in the records branch has been aligned with the updated spec: https://hg.openjdk.java.net/amber/amber/rev/52a9226db842 -Chris. From gavin.bierman at oracle.com Tue Oct 22 13:34:15 2019 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Tue, 22 Oct 2019 14:34:15 +0100 Subject: Draft JLS spec for JEP 305: Pattern matching for instanceof In-Reply-To: References: <2596DE6A-0154-488A-9EDC-031A6E300CF0@oracle.com> Message-ID: <26B46A27-B3B8-4686-9758-56B99E5F86FA@oracle.com> > On 21 Oct 2019, at 15:49, Chris Hegarty wrote: > > > >> On 21 Oct 2019, at 10:50, Gavin Bierman wrote: >> >> A second, and hopefully final, draft language spec for JEP 305 (Pattern matching for instanceof) is available at: >> >> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html > > While proofreading, I came across a minor issue in 15.20.2: > > "? The expression RelationalExpression is compatible with the type ReferenceType if (i) RelationalExpression can be converted to type ReferenceType by casting conversion (5.5), and (ii) the casting conversion does not make use of a narrowing reference conversion which is unchecked (5.1.6.2). If ReferenceType is not compatible with ReferenceType then a compile-time error occurs." > > Should be: > If *RelationalExpression* is not compatible with ReferenceType then a compile-time error occurs. Thanks. Will fix. Gavin From peter.levart at gmail.com Fri Oct 25 10:34:04 2019 From: peter.levart at gmail.com (Peter Levart) Date: Fri, 25 Oct 2019 12:34:04 +0200 Subject: [sealed] Sealed local classes? In-Reply-To: <1458956846.1616463.1570659220610.JavaMail.zimbra@u-pem.fr> References: <896473e3-a6df-b8d4-91c9-779bf70954a2@oracle.com> <1458956846.1616463.1570659220610.JavaMail.zimbra@u-pem.fr> Message-ID: <3bae3906-94f5-851a-a429-9b64fec2dfb6@gmail.com> On 10/10/19 12:13 AM, Remi Forax wrote: > I agree, PermittedSubtypes should only contain stable names :) Well, since inference always happens inside a compilation unit, even "unstable" names are OK as all the classes in compilation unit are (re)compiled together. Regards, Peter > > R?mi > > ----- Mail original ----- >> De: "Brian Goetz" >> ?: "amber-spec-experts" >> Envoy?: Mercredi 9 Octobre 2019 23:35:48 >> Objet: Re: [sealed] Sealed local classes? >>> Proposal: ban `sealed` and `non-sealed` modifiers on _local_ classes >>> and interfaces. >> And we would want to extend the ban we have for the other two forms of >> "subclasses inside implementations", lambdas and inner classes, to local >> classes. From forax at univ-mlv.fr Fri Oct 25 14:16:06 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 25 Oct 2019 14:16:06 +0000 Subject: [sealed] Sealed local classes? In-Reply-To: <3bae3906-94f5-851a-a429-9b64fec2dfb6@gmail.com> References: <896473e3-a6df-b8d4-91c9-779bf70954a2@oracle.com> <1458956846.1616463.1570659220610.JavaMail.zimbra@u-pem.fr> <3bae3906-94f5-851a-a429-9b64fec2dfb6@gmail.com> Message-ID: <6785A817-98F5-4CC6-B5E1-12C8CA27A8FC@univ-mlv.fr> If you see sealed types in isolation yes, but once you think that the compiler will check exhaustiveness of a switch using those names, the names has to be stable and human readable. Remi On October 25, 2019 10:34:04 AM UTC, Peter Levart wrote: > > >On 10/10/19 12:13 AM, Remi Forax wrote: >> I agree, PermittedSubtypes should only contain stable names :) > >Well, since inference always happens inside a compilation unit, even >"unstable" names are OK as all the classes in compilation unit are >(re)compiled together. > > >Regards, Peter > >> >> R?mi >> >> ----- Mail original ----- >>> De: "Brian Goetz" >>> ?: "amber-spec-experts" >>> Envoy?: Mercredi 9 Octobre 2019 23:35:48 >>> Objet: Re: [sealed] Sealed local classes? >>>> Proposal: ban `sealed` and `non-sealed` modifiers on _local_ >classes >>>> and interfaces. >>> And we would want to extend the ban we have for the other two forms >of >>> "subclasses inside implementations", lambdas and inner classes, to >local >>> classes. -- Envoy? de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma bri?vet?. From zimmermann.tho at gmail.com Mon Oct 28 12:23:33 2019 From: zimmermann.tho at gmail.com (Thomas Zimmermann) Date: Mon, 28 Oct 2019 13:23:33 +0100 Subject: New candidate JEP: 361: Switch Expressions (Standard) In-Reply-To: References: Message-ID: <0b19e9e5-18d0-0bea-9d0c-3a2b488b64b9@gmail.com> Hello dear OpenJDK developers! I have some feedback regarding switch expressions, more precisely the new non-exhaustive arrow-switch statements. The original code was in Kotlin, but I recreated the structure in Java and the problem remains the same. Context: An Android app showing the current location on a map. The UI is listening to a stream of update events that cover all corner cases of the dynamic environment that is Android: enum LocationUpdate { ??? SUCCESS, // new location, yay ??? UNKNOWN, // no location fix for whatever reason ??? PERMISSION_DENIED // user revoked permission while we were listening to GPS :( } (`LocationUpdate` should really be a sealed type, but let's stay with one preview feature for now) The UI will react to each update as follows: void onLocationUpdate(LocationUpdate update) { ??? switch (update) { ??????? case SUCCESS -> updateLocationMarker(); ??????? case UNKNOWN -> removeLocationMarker(); ??????? // woops, forgot to handle permission denied case ??? } ??? doSomethingElse(); } I hope you can see my problem: I expected the compiler to help me even when the switch does not produce a value. The most obvious work around is pretty terrible (useless variable, yielding arbitrary values): void onLocationUpdate(LocationUpdate update) { ??? var ignored = switch (update) { ??????? case SUCCESS-> { ??????????? updateLocationMarker(); ??????????? yield true; ??????? } ??????? case UNKNOWN-> { ??????????? removeLocationMarker(); ??????????? yield true; ??????? } ??????? // compiler error, good ??? }; ??? doSomethingElse(); } Probably shortsighted proposal: Make arrow-switch statements exhaustive (for sealed types and enums at least). Getting back the non-exhaustiveness if desired seems simple in this case: switch (update) { ??? case SUCCESS -> updateLocationMarker(); ??? case UNKNOWN -> removeLocationMarker(); ??? // don't care about the other cases ??? default -> {} } ... whereas getting exhaustiveness from the non-exhaustive switch is hard (see work around above). JEP 361 [0] only says "Obviously |switch|statements are not required to be exhaustive". Was this discussed previously? I feel like I am missing something. As a sidenote, Kotlin is also missing this feature [1], maybe Java can learn from this (IMO) mistake? [0] https://openjdk.java.net/jeps/361 [1] https://youtrack.jetbrains.com/issue/KT-12380 Best regards, Thomas Zimmermann P.S.: I'm very excited about the new upcoming features, stellar work everyone! From brian.goetz at oracle.com Tue Oct 29 22:09:15 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 29 Oct 2019 18:09:15 -0400 Subject: New candidate JEP: 361: Switch Expressions (Standard) In-Reply-To: <967b41a5-0f40-4044-b6f8-58d235bc34fc@oracle.com> References: <0b19e9e5-18d0-0bea-9d0c-3a2b488b64b9@gmail.com> <967b41a5-0f40-4044-b6f8-58d235bc34fc@oracle.com> Message-ID: <9c045910-16d2-aa48-364c-b21c075cc4bd@oracle.com> The asymmetry with respect to totality between switch expressions and statements is indeed unfortunate, and one we approached from a number of angles, but we are boxed in on one side by compatibility, and on the other by semantics.? Expressions _must_ be total, so we have to enforce totality for switch expressions (a non-total expression is nonsensical.)? On the other hand, we already have switch statements, and they are currently not total, and trying to make them total would break existing code.? So we don't have a lot of latitude in our defaults. > JEP 361 [0] only says "Obviously |switch|statements are not required > to be exhaustive". > Was this discussed previously? I feel like I am missing something. It flows from the existing definition of switch statements, which are not required to be exhaustive, and so the world is full of non-exhaustive switch statements that handle some portion of the state space (perhaps either picking off the "easy" states, or pruning off the impossible ones and throwing an exception), and then continue on.? We can't break this code, so it's here to stay. It is possible that in the future, we'll expose a way to say "total statement switch", which would engage the compiler's aid in proving exhaustiveness.? We couldn't just spell that `switch`, for reasons above, though. (That this is just one more reason why "expressions are better than statements", and we should prefer to program with expressions when we can, is not very comforting.) Your proposal: > Probably shortsighted proposal: > Make arrow-switch statements exhaustive (for sealed types and enums at > least). was not previously considered, but there's a good reason to not like it, which is: it undermines orthogonality.? The improvements to switch here were several orthogonal (or mostly orthogonal) changes: ?- expression vs statement ?- single-consequence vs multi-consequence case labels ?- multiple case labels on one line That users are free to mix and match these is a benefit; composing a complex feature out of orthogonal simpler features make it easier to reason about, and hidden couplings between them would show up as sharp edges.? (For example, if arrow-switch statements were exhaustive but colon-switch statements were not, this means that the obvious refactoring from one to the other has subtly different semantics.) Yes, we do have a hidden coupling with respect to exhaustiveness; we don't like it, but we don't see a cure that isn't far worse than the disease.? (Let's not rehash the supposed cure of "make a new syntactic form, and leave switch to rot"; this far-worse cure has already been discussed to death.) So, it seems likely the best we can do is provide a way to opt into exhaustiveness analysis for statement switches.? This might be a modified keyword (e.g., `total-switch`), or some adornment of the default clause (`default: unreachable`), or something else.? But the urgency to do this NOW is limited, at least until we have more sources of exhaustiveness (sealed types) that are relevant to switch (pattern support in switch.) Cheers, -Brian > Subject: Re: New candidate JEP: 361: Switch Expressions (Standard) > Date: Mon, 28 Oct 2019 13:23:33 +0100 > From: Thomas Zimmermann > Reply-To: Amber Expert Group Observers > > To: amber-spec-observers at openjdk.java.net > > Hello dear OpenJDK developers! > > I have some feedback regarding switch expressions, more precisely the > new non-exhaustive arrow-switch statements. > The original code was in Kotlin, but I recreated the structure in Java > and the problem remains the same. > > Context: > An Android app showing the current location on a map. The UI is > listening to a stream of update events that cover > all corner cases of the dynamic environment that is Android: > > enum LocationUpdate { > ??? SUCCESS, // new location, yay > ??? UNKNOWN, // no location fix for whatever reason > ??? PERMISSION_DENIED // user revoked permission while wewere > listening to GPS :( > } > > (`LocationUpdate` should really be a sealed type, but let's stay with > one preview feature for now) > > The UI will react to each update as follows: > > void onLocationUpdate(LocationUpdate update) { > ??? switch (update) { > ??????? case SUCCESS -> updateLocationMarker(); > ??????? case UNKNOWN -> removeLocationMarker(); > ??????? // woops, forgot to handle permission denied case > ??? } > ??? doSomethingElse(); > } > > I hope you can see my problem: I expected the compiler to help me even > when the switch does not produce a value. > The most obvious work around is pretty terrible (useless variable, > yielding arbitrary values): > > void onLocationUpdate(LocationUpdate update) { > ??? var ignored = switch (update) { > ??????? case SUCCESS-> { > ??????????? updateLocationMarker(); > ??????????? yieldtrue; > ??????? } > ??????? case UNKNOWN-> { > ??????????? removeLocationMarker(); > ??????????? yieldtrue; > ??????? } > ??????? // compiler error, good > ??? }; > ??? doSomethingElse(); > } > > Probably shortsighted proposal: > Make arrow-switch statements exhaustive (for sealed types and enums at > least). > Getting back the non-exhaustiveness if desired seems simple in this case: > > switch (update) { > ??? case SUCCESS -> updateLocationMarker(); > ??? case UNKNOWN -> removeLocationMarker(); > ??? // don't care about the other cases > ??? default -> {} > } > > ... whereas getting exhaustiveness from the non-exhaustive switch is > hard (see work around above). > > > JEP 361 [0] only says "Obviously |switch|statements are not required > to be exhaustive". > Was this discussed previously? I feel like I am missing something. > > As a sidenote, Kotlin is also missing this feature [1], maybe Java can > learn from this (IMO) mistake? > > [0] https://openjdk.java.net/jeps/361 > [1] https://youtrack.jetbrains.com/issue/KT-12380 > > Best regards, > Thomas Zimmermann > > P.S.: I'm very excited about the new upcoming features, stellar work > everyone! From forax at univ-mlv.fr Wed Oct 30 11:54:56 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 30 Oct 2019 12:54:56 +0100 (CET) Subject: Text blok follow up Message-ID: <1541924396.992533.1572436496071.JavaMail.zimbra@u-pem.fr> Hi all, Jim, Brian, please do not use the same name "Escape Sequences For Line Continuation and White Space (Preview)", for two different features, one which is withdrawn (JDK-8227870) and one which is still alive (JDK-8233117). I'm coming back from JokerConf in Russia and everybody there were in full confusion mode about that. Moreover, my personal feeling is that we should stop to add such incremental niche feature, at least for now, and move to solve the real issue we have left, raw strings, because while i agree that de-coupling the two features text block and raw string was necessary, it also means that we still have no support for raw strings. R?mi From brian.goetz at oracle.com Wed Oct 30 12:30:06 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 30 Oct 2019 08:30:06 -0400 Subject: Text blok follow up In-Reply-To: <1541924396.992533.1572436496071.JavaMail.zimbra@u-pem.fr> References: <1541924396.992533.1572436496071.JavaMail.zimbra@u-pem.fr> Message-ID: First of all, the two are of different orders of magnitude; adding a few more escape sequences is not remotely the same thing as raw strings. So it?s not either/or. But, more importantly, I just don?t think raw strings are that urgent any more. Text blocks addressed 95% of the pain; sure, we could go back for that last 5%, and maybe we should some day, but I don?t think its anywhere near the top of the priority list any more. I?d rather invest the effort in getting to pattern matching, or valhalla, or any number of other things sooner. > On Oct 30, 2019, at 7:54 AM, Remi Forax wrote: > > Hi all, > Jim, Brian, > please do not use the same name "Escape Sequences For Line Continuation and White Space (Preview)", > for two different features, one which is withdrawn (JDK-8227870) and one which is still alive (JDK-8233117). > > I'm coming back from JokerConf in Russia and everybody there were in full confusion mode about that. > > Moreover, my personal feeling is that we should stop to add such incremental niche feature, at least for now, and move to solve the real issue we have left, raw strings, because while i agree that de-coupling the two features text block and raw string was necessary, it also means that we still have no support for raw strings. > > R?mi > From forax at univ-mlv.fr Wed Oct 30 13:13:40 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 30 Oct 2019 13:13:40 +0000 Subject: Text blok follow up In-Reply-To: References: <1541924396.992533.1572436496071.JavaMail.zimbra@u-pem.fr> Message-ID: On October 30, 2019 12:30:06 PM UTC, Brian Goetz wrote: >First of all, the two are of different orders of magnitude; adding a >few more escape sequences is not remotely the same thing as raw >strings. So it?s not either/or. > >But, more importantly, I just don?t think raw strings are that urgent >any more. Text blocks addressed 95% of the pain; sure, we could go >back for that last 5%, and maybe we should some day, but I don?t think >its anywhere near the top of the priority list any more. I?d rather >invest the effort in getting to pattern matching, or valhalla, or any >number of other things sooner. Ah, interesting ! For me, the fact that you have to despecialize every slash inside a regex string is a use case big enough to justify raw strings. I will happily admit that I'm biased by the fact that I see my students struggling to write the correct string to feed Pattern.compile or String.split every year. But maybe a specific syntax for regex that create a Pattern using a condy is a better idea ? Remi > >> On Oct 30, 2019, at 7:54 AM, Remi Forax wrote: >> >> Hi all, >> Jim, Brian, >> please do not use the same name "Escape Sequences For Line >Continuation and White Space (Preview)", >> for two different features, one which is withdrawn (JDK-8227870) and >one which is still alive (JDK-8233117). >> >> I'm coming back from JokerConf in Russia and everybody there were in >full confusion mode about that. >> >> Moreover, my personal feeling is that we should stop to add such >incremental niche feature, at least for now, and move to solve the real >issue we have left, raw strings, because while i agree that de-coupling >the two features text block and raw string was necessary, it also means >that we still have no support for raw strings. >> >> R?mi >> -- Envoy? de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma bri?vet?. From brian.goetz at oracle.com Wed Oct 30 13:18:09 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 30 Oct 2019 09:18:09 -0400 Subject: Text blok follow up In-Reply-To: References: <1541924396.992533.1572436496071.JavaMail.zimbra@u-pem.fr> Message-ID: <2C69C08B-71DC-45FF-8231-7C861A099B51@oracle.com> Indeed, regex is the biggest offender, with windows paths a distant second. To be fair, the escape mangling is only a small part of the challenge of reading regular expressions :) Perhaps your students would like a library like: https://github.com/VerbalExpressions/JavaVerbalExpressions at least while they are learning the concepts? > On Oct 30, 2019, at 9:13 AM, Remi Forax wrote: > > > > On October 30, 2019 12:30:06 PM UTC, Brian Goetz > wrote: >> First of all, the two are of different orders of magnitude; adding a >> few more escape sequences is not remotely the same thing as raw >> strings. So it?s not either/or. >> >> But, more importantly, I just don?t think raw strings are that urgent >> any more. Text blocks addressed 95% of the pain; sure, we could go >> back for that last 5%, and maybe we should some day, but I don?t think >> its anywhere near the top of the priority list any more. I?d rather >> invest the effort in getting to pattern matching, or valhalla, or any >> number of other things sooner. > > Ah, interesting ! > For me, the fact that you have to despecialize every slash inside a regex string is a use case big enough to justify raw strings. > I will happily admit that I'm biased by the fact that I see my students struggling to write the correct string to feed Pattern.compile or String.split every year. > > But maybe a specific syntax for regex that create a Pattern using a condy is a better idea ? > > Remi > >> >>> On Oct 30, 2019, at 7:54 AM, Remi Forax wrote: >>> >>> Hi all, >>> Jim, Brian, >>> please do not use the same name "Escape Sequences For Line >> Continuation and White Space (Preview)", >>> for two different features, one which is withdrawn (JDK-8227870) and >> one which is still alive (JDK-8233117). >>> >>> I'm coming back from JokerConf in Russia and everybody there were in >> full confusion mode about that. >>> >>> Moreover, my personal feeling is that we should stop to add such >> incremental niche feature, at least for now, and move to solve the real >> issue we have left, raw strings, because while i agree that de-coupling >> the two features text block and raw string was necessary, it also means >> that we still have no support for raw strings. >>> >>> R?mi >>> > > -- > Envoy? de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma bri?vet?. From zimmermann.tho at gmail.com Wed Oct 30 13:54:07 2019 From: zimmermann.tho at gmail.com (Thomas Zimmermann) Date: Wed, 30 Oct 2019 14:54:07 +0100 Subject: New candidate JEP: 361: Switch Expressions (Standard) In-Reply-To: <9c045910-16d2-aa48-364c-b21c075cc4bd@oracle.com> References: <0b19e9e5-18d0-0bea-9d0c-3a2b488b64b9@gmail.com> <967b41a5-0f40-4044-b6f8-58d235bc34fc@oracle.com> <9c045910-16d2-aa48-364c-b21c075cc4bd@oracle.com> Message-ID: <983b2e06-f4ed-d6ac-e184-c5abfa5e2d9d@gmail.com> I am satisfied with the reasoning and comforted in knowing that the issue was given due consideration. :) My initial expectation probably came from watching your talks on the subject, but those mostly show examples of the expression form. Maybe it makes sense to call out this difference? > But the urgency to do this NOW is limited, at least until we have more sources of exhaustiveness (sealed types) [...] Agreed. Thank you for taking the time to explain this so clearly! Best regards, Thomas Zimmermann On 10/29/19 11:09 PM, brian.goetz at oracle.com (Brian Goetz) wrote: > The asymmetry with respect to totality between switch expressions and > statements is indeed unfortunate, and one we approached from a number of > angles, but we are boxed in on one side by compatibility, and on the > other by semantics.? Expressions _must_ be total, so we have to enforce > totality for switch expressions (a non-total expression is > nonsensical.)? On the other hand, we already have switch statements, and > they are currently not total, and trying to make them total would break > existing code.? So we don't have a lot of latitude in our defaults. > >> JEP 361 [0] only says "Obviously |switch|statements are not required >> to be exhaustive". >> Was this discussed previously? I feel like I am missing something. > It flows from the existing definition of switch statements, which are > not required to be exhaustive, and so the world is full of > non-exhaustive switch statements that handle some portion of the state > space (perhaps either picking off the "easy" states, or pruning off the > impossible ones and throwing an exception), and then continue on.? We > can't break this code, so it's here to stay. > > It is possible that in the future, we'll expose a way to say "total > statement switch", which would engage the compiler's aid in proving > exhaustiveness.? We couldn't just spell that `switch`, for reasons > above, though. > > (That this is just one more reason why "expressions are better than > statements", and we should prefer to program with expressions when we > can, is not very comforting.) > > Your proposal: > >> Probably shortsighted proposal: >> Make arrow-switch statements exhaustive (for sealed types and enums at >> least). > was not previously considered, but there's a good reason to not like it, > which is: it undermines orthogonality.? The improvements to switch here > were several orthogonal (or mostly orthogonal) changes: > ?- expression vs statement > ?- single-consequence vs multi-consequence case labels > ?- multiple case labels on one line > > That users are free to mix and match these is a benefit; composing a > complex feature out of orthogonal simpler features make it easier to > reason about, and hidden couplings between them would show up as sharp > edges.? (For example, if arrow-switch statements were exhaustive but > colon-switch statements were not, this means that the obvious > refactoring from one to the other has subtly different semantics.) > > Yes, we do have a hidden coupling with respect to exhaustiveness; we > don't like it, but we don't see a cure that isn't far worse than the > disease.? (Let's not rehash the supposed cure of "make a new syntactic > form, and leave switch to rot"; this far-worse cure has already been > discussed to death.) > > So, it seems likely the best we can do is provide a way to opt into > exhaustiveness analysis for statement switches.? This might be a > modified keyword (e.g., `total-switch`), or some adornment of the > default clause (`default: unreachable`), or something else.? But the > urgency to do this NOW is limited, at least until we have more sources > of exhaustiveness (sealed types) that are relevant to switch (pattern > support in switch.) > > Cheers, > -Brian From forax at univ-mlv.fr Wed Oct 30 15:04:12 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 30 Oct 2019 15:04:12 +0000 Subject: Text blok follow up In-Reply-To: <2C69C08B-71DC-45FF-8231-7C861A099B51@oracle.com> References: <1541924396.992533.1572436496071.JavaMail.zimbra@u-pem.fr> <2C69C08B-71DC-45FF-8231-7C861A099B51@oracle.com> Message-ID: <08B894CD-20E5-48D8-A627-9C7282A6A316@univ-mlv.fr> On October 30, 2019 1:18:09 PM UTC, Brian Goetz wrote: >Indeed, regex is the biggest offender, with windows paths a distant >second. > >To be fair, the escape mangling is only a small part of the challenge >of reading regular expressions :) True in general. In my case, and I believe this is true for a lot of universities, students starts with Python as first language, and in Python you have the r'foo' syntax. Then in Java, most of them don't struggle with the concept of regex or automata already seen but how to properly escape the regex string (with capturing groups) because the inability to express a raw string in Java. > >> On Oct 30, 2019, at 9:13 AM, Remi Forax wrote: >> >> >> >> On October 30, 2019 12:30:06 PM UTC, Brian Goetz >> wrote: >>> First of all, the two are of different orders of magnitude; adding a >>> few more escape sequences is not remotely the same thing as raw >>> strings. So it?s not either/or. >>> >>> But, more importantly, I just don?t think raw strings are that >urgent >>> any more. Text blocks addressed 95% of the pain; sure, we could go >>> back for that last 5%, and maybe we should some day, but I don?t >think >>> its anywhere near the top of the priority list any more. I?d rather >>> invest the effort in getting to pattern matching, or valhalla, or >any >>> number of other things sooner. >> >> Ah, interesting ! >> For me, the fact that you have to despecialize every slash inside a >regex string is a use case big enough to justify raw strings. >> I will happily admit that I'm biased by the fact that I see my >students struggling to write the correct string to feed Pattern.compile >or String.split every year. >> >> But maybe a specific syntax for regex that create a Pattern using a >condy is a better idea ? >> >> Remi >> >>> >>>> On Oct 30, 2019, at 7:54 AM, Remi Forax wrote: >>>> >>>> Hi all, >>>> Jim, Brian, >>>> please do not use the same name "Escape Sequences For Line >>> Continuation and White Space (Preview)", >>>> for two different features, one which is withdrawn (JDK-8227870) >and >>> one which is still alive (JDK-8233117). >>>> >>>> I'm coming back from JokerConf in Russia and everybody there were >in >>> full confusion mode about that. >>>> >>>> Moreover, my personal feeling is that we should stop to add such >>> incremental niche feature, at least for now, and move to solve the >real >>> issue we have left, raw strings, because while i agree that >de-coupling >>> the two features text block and raw string was necessary, it also >means >>> that we still have no support for raw strings. >>>> >>>> R?mi >>>> >> >> -- >> Envoy? de mon appareil Android avec Courriel K-9 Mail. Veuillez >excuser ma bri?vet?. -- Envoy? de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma bri?vet?. From vicente.romero at oracle.com Thu Oct 31 12:21:18 2019 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 31 Oct 2019 08:21:18 -0400 Subject: forbidding serialization methods as members of records Message-ID: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> Hi, In the past we discussed about forbidding the declaration of some serialization related methods in records. In particular: writeObject(ObjectOutputStream) readObjectNoData() readObject(ObjectInputStream) I wonder if we still want to enforce that restriction, meaning that it should be reflected in the spec, or if it is not necessary anymore, Thanks, Vicente From chris.hegarty at oracle.com Thu Oct 31 12:25:53 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Thu, 31 Oct 2019 12:25:53 +0000 Subject: forbidding serialization methods as members of records In-Reply-To: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> Message-ID: <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> > On 31 Oct 2019, at 12:21, Vicente Romero wrote: > > Hi, > > In the past we discussed about forbidding the declaration of some serialization related methods in records. In particular: > > writeObject(ObjectOutputStream) > readObjectNoData() > readObject(ObjectInputStream) > I wonder if we still want to enforce that restriction, meaning that it should be reflected in the spec, or if it is not necessary anymore, Where we ended up with Serializable Records, is that the runtime is specified to ignore these methods if they appear in a serializable record ( there are tests that assert this ). The javac restriction is no longer strictly necessary, but of course catches effectively-useless declarations early, and without resorting checkers, inspection, etc. -Chris. From forax at univ-mlv.fr Thu Oct 31 12:33:49 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 31 Oct 2019 13:33:49 +0100 (CET) Subject: forbidding serialization methods as members of records In-Reply-To: <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> Message-ID: <1164147528.1249688.1572525229179.JavaMail.zimbra@u-pem.fr> > De: "Chris Hegarty" > ?: "Vicente Romero" > Cc: "amber-spec-experts" > Envoy?: Jeudi 31 Octobre 2019 13:25:53 > Objet: Re: forbidding serialization methods as members of records >> On 31 Oct 2019, at 12:21, Vicente Romero < [ mailto:vicente.romero at oracle.com | >> vicente.romero at oracle.com ] > wrote: >> Hi, >> In the past we discussed about forbidding the declaration of some serialization >> related methods in records. In particular: >> writeObject(ObjectOutputStream) >> readObjectNoData() >> readObject(ObjectInputStream) >> I wonder if we still want to enforce that restriction, meaning that it should be >> reflected in the spec, or if it is not necessary anymore, > Where we ended up with Serializable Records, is that the runtime is specified to > ignore these methods if they appear in a serializable record ( there are tests > that assert this ). The javac restriction is no longer strictly necessary, but > of course catches effectively-useless declarations early, and without resorting > checkers, inspection, etc. It is necessary from a user point of view to have a javac error, having something that silently fails is the worst in term of user experience. > -Chris. R?mi From vicente.romero at oracle.com Thu Oct 31 12:51:04 2019 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 31 Oct 2019 08:51:04 -0400 Subject: forbidding serialization methods as members of records In-Reply-To: <1164147528.1249688.1572525229179.JavaMail.zimbra@u-pem.fr> References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> <1164147528.1249688.1572525229179.JavaMail.zimbra@u-pem.fr> Message-ID: On 10/31/19 8:33 AM, Remi Forax wrote: > > > ------------------------------------------------------------------------ > > *De: *"Chris Hegarty" > *?: *"Vicente Romero" > *Cc: *"amber-spec-experts" > *Envoy?: *Jeudi 31 Octobre 2019 13:25:53 > *Objet: *Re: forbidding serialization methods as members of records > > > > On 31 Oct 2019, at 12:21, Vicente Romero > > > wrote: > > Hi, > > In the past we discussed about forbidding the declaration of > some serialization related methods in records. In particular: > > writeObject(ObjectOutputStream) > readObjectNoData() > readObject(ObjectInputStream) > > I wonder if we still want to enforce that restriction, meaning > that it should be reflected in the spec, or if it is not > necessary anymore, > > > Where we ended up with Serializable Records, is that the runtime > is specified to ignore these methods if they appear in a > serializable record ( there are tests that assert this ). ?The > javac restriction is no longer strictly necessary, but of course > catches effectively-useless declarations early, and without > resorting checkers, inspection, etc. > > > It is necessary from a user point of view to have a javac error, > having something that silently fails is the worst in term of user > experience. would a warning be an option? > > > -Chris. > > > R?mi > Vicente From forax at univ-mlv.fr Thu Oct 31 12:56:14 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 31 Oct 2019 13:56:14 +0100 (CET) Subject: forbidding serialization methods as members of records In-Reply-To: References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> <1164147528.1249688.1572525229179.JavaMail.zimbra@u-pem.fr> Message-ID: <1391526431.1254917.1572526574090.JavaMail.zimbra@u-pem.fr> > De: "Vicente Romero" > ?: "Remi Forax" , "Chris Hegarty" > Cc: "amber-spec-experts" > Envoy?: Jeudi 31 Octobre 2019 13:51:04 > Objet: Re: forbidding serialization methods as members of records > On 10/31/19 8:33 AM, Remi Forax wrote: >>> De: "Chris Hegarty" [ mailto:chris.hegarty at oracle.com | >>> ] >>> ?: "Vicente Romero" [ mailto:vicente.romero at oracle.com | >>> ] >>> Cc: "amber-spec-experts" [ mailto:amber-spec-experts at openjdk.java.net | >>> ] >>> Envoy?: Jeudi 31 Octobre 2019 13:25:53 >>> Objet: Re: forbidding serialization methods as members of records >>>> On 31 Oct 2019, at 12:21, Vicente Romero < [ mailto:vicente.romero at oracle.com | >>>> vicente.romero at oracle.com ] > wrote: >>>> Hi, >>>> In the past we discussed about forbidding the declaration of some serialization >>>> related methods in records. In particular: >>>> writeObject(ObjectOutputStream) >>>> readObjectNoData() >>>> readObject(ObjectInputStream) >>>> I wonder if we still want to enforce that restriction, meaning that it should be >>>> reflected in the spec, or if it is not necessary anymore, >>> Where we ended up with Serializable Records, is that the runtime is specified to >>> ignore these methods if they appear in a serializable record ( there are tests >>> that assert this ). The javac restriction is no longer strictly necessary, but >>> of course catches effectively-useless declarations early, and without resorting >>> checkers, inspection, etc. >> It is necessary from a user point of view to have a javac error, having >> something that silently fails is the worst in term of user experience. > would a warning be an option? Why letting the option for a user to shoot itself in the foot ? It's not like it will work sometimes. R?mi >>> -Chris. >> R?mi > Vicente From jerven.bolleman at sib.swiss Thu Oct 31 13:04:41 2019 From: jerven.bolleman at sib.swiss (Jerven Bolleman) Date: Thu, 31 Oct 2019 14:04:41 +0100 Subject: forbidding serialization methods as members of records In-Reply-To: <1391526431.1254917.1572526574090.JavaMail.zimbra@u-pem.fr> References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> <1164147528.1249688.1572525229179.JavaMail.zimbra@u-pem.fr> <1391526431.1254917.1572526574090.JavaMail.zimbra@u-pem.fr> Message-ID: Dear Vicente, All, I second R?mi, I think it is a long standing Java principle to not allow dead code as much as possible. It is my belief that this should be true here as well. If the code can't do anything it should not be allowed to exist. I can already imagine the hours wasted wondering why code someone wrote is not being executed. Especially if upon otherwise reasonable belief it should have. Regards, Jerven On 10/31/19 1:56 PM, forax at univ-mlv.fr wrote: >> De: "Vicente Romero" >> ?: "Remi Forax" , "Chris Hegarty" >> Cc: "amber-spec-experts" >> Envoy?: Jeudi 31 Octobre 2019 13:51:04 >> Objet: Re: forbidding serialization methods as members of records > >> On 10/31/19 8:33 AM, Remi Forax wrote: > >>>> De: "Chris Hegarty" [ mailto:chris.hegarty at oracle.com | >>>> ] >>>> ?: "Vicente Romero" [ mailto:vicente.romero at oracle.com | >>>> ] >>>> Cc: "amber-spec-experts" [ mailto:amber-spec-experts at openjdk.java.net | >>>> ] >>>> Envoy?: Jeudi 31 Octobre 2019 13:25:53 >>>> Objet: Re: forbidding serialization methods as members of records > >>>>> On 31 Oct 2019, at 12:21, Vicente Romero < [ mailto:vicente.romero at oracle.com | >>>>> vicente.romero at oracle.com ] > wrote: > >>>>> Hi, > >>>>> In the past we discussed about forbidding the declaration of some serialization >>>>> related methods in records. In particular: > >>>>> writeObject(ObjectOutputStream) >>>>> readObjectNoData() >>>>> readObject(ObjectInputStream) >>>>> I wonder if we still want to enforce that restriction, meaning that it should be >>>>> reflected in the spec, or if it is not necessary anymore, > >>>> Where we ended up with Serializable Records, is that the runtime is specified to >>>> ignore these methods if they appear in a serializable record ( there are tests >>>> that assert this ). The javac restriction is no longer strictly necessary, but >>>> of course catches effectively-useless declarations early, and without resorting >>>> checkers, inspection, etc. > >>> It is necessary from a user point of view to have a javac error, having >>> something that silently fails is the worst in term of user experience. > >> would a warning be an option? > Why letting the option for a user to shoot itself in the foot ? It's not like it will work sometimes. > > R?mi > >>>> -Chris. > >>> R?mi > >> Vicente From jonathan.gibbons at oracle.com Thu Oct 31 14:09:11 2019 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 31 Oct 2019 07:09:11 -0700 Subject: forbidding serialization methods as members of records In-Reply-To: <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> Message-ID: <956ded11-2de5-5bd1-491e-763863d0a4f4@oracle.com> On 10/31/19 5:25 AM, Chris Hegarty wrote: > >> On 31 Oct 2019, at 12:21, Vicente Romero wrote: >> >> Hi, >> >> In the past we discussed about forbidding the declaration of some serialization related methods in records. In particular: >> >> writeObject(ObjectOutputStream) >> readObjectNoData() >> readObject(ObjectInputStream) >> I wonder if we still want to enforce that restriction, meaning that it should be reflected in the spec, or if it is not necessary anymore, > Where we ended up with Serializable Records, is that the runtime is specified to ignore these methods if they appear in a serializable record ( there are tests that assert this ). The javac restriction is no longer strictly necessary, but of course catches effectively-useless declarations early, and without resorting checkers, inspection, etc. > > -Chris. > This seems to be in line with the general philosophy of the serialization specification in which candidate declarations for serialization-related members are ignored if they don't fulfill all the required properties.? Without commenting on the merits of the policy, it would at least be good if the policy was consistent. Failing that, a warning (-Xlint:serial) would be in line with current javac behavior. -- Jon From maurizio.cimadamore at oracle.com Thu Oct 31 14:15:36 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 31 Oct 2019 14:15:36 +0000 Subject: forbidding serialization methods as members of records In-Reply-To: <956ded11-2de5-5bd1-491e-763863d0a4f4@oracle.com> References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> <956ded11-2de5-5bd1-491e-763863d0a4f4@oracle.com> Message-ID: <1a7f4011-379d-c5db-888b-b0a5fdb87af2@oracle.com> On 31/10/2019 14:09, Jonathan Gibbons wrote: > > On 10/31/19 5:25 AM, Chris Hegarty wrote: >> >>> On 31 Oct 2019, at 12:21, Vicente Romero >>> wrote: >>> >>> Hi, >>> >>> In the past we discussed about forbidding the declaration of some >>> serialization related methods in records. In particular: >>> >>> ? writeObject(ObjectOutputStream) >>> readObjectNoData() >>> readObject(ObjectInputStream) >>> I wonder if we still want to enforce that restriction, meaning that >>> it should be reflected in the spec, or if it is not necessary anymore, >> Where we ended up with Serializable Records, is that the runtime is >> specified to ignore these methods if they appear in a serializable >> record ( there are tests that assert this ).? The javac restriction >> is no longer strictly necessary, but of course catches >> effectively-useless declarations early, and without resorting >> checkers, inspection, etc. >> >> -Chris. >> > This seems to be in line with the general philosophy of the > serialization specification in which candidate declarations for > serialization-related members are ignored if they don't fulfill all > the required properties.? Without commenting on the merits of the > policy, it would at least be good if the policy was consistent. > Failing that, a warning (-Xlint:serial) would be in line with current > javac behavior. I think we're talking about useless declarations - to me a warning is exactly the right fit for something like this. There's also a general desire to keep the JLS free from any jargon introduced by the serialization spec (and for a good reason). A warning gives us flexibility in that respect - an hard error doesn't (as the JLS will have to justify it). Maurizio > > -- Jon > From gavin.bierman at oracle.com Thu Oct 31 14:17:34 2019 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Thu, 31 Oct 2019 14:17:34 +0000 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: An updated draft language spec for JEP 359 (Records) is available at: http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html (Alongside is a draft JVM spec for this feature: http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html ) As always, please email me any comments/thoughts/bugs. Thanks, Gavin > On 23 Aug 2019, at 22:25, Gavin Bierman wrote: > > A draft language spec for records is available at: > > http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-jls.html > > This spec doesn?t yet discuss varargs records - to appear in the next draft. > > All comments welcomed! > > Thanks, > Gavin From maurizio.cimadamore at oracle.com Thu Oct 31 14:29:57 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 31 Oct 2019 14:29:57 +0000 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: Related to the earlier discussion on forbidden record members - how is this section still relevant? "It is a compile-time error for a record declaration to declare a record component with the name |clone|, |finalize|, |getClass|, |hashCode|, |notify|, |notifyAll|, |readObjectNoData|, |readResolve|, |serialPersistentFields|, |serialVersionUID|, |toString|, |wait|, or |writeReplace|." Chris says that the serialization spec ignores all the serialization-related methods if they appear inside a record; should we lift the restrictions? In the grammar for records, I find it odd that we basically say that record members are class members plus compact constructor, but then we revert to say that instance initializer are not allowed. I wonder if a more specific production for the record body would be useful and more direct here? I note an asymmetry between the rules for canonical constructor and compact constructor; in one we say: "Every field corresponding to a record component of R must be definitely assigned and moreover not definitely unassigned (16.9) at the end of the body of the canonical constructor." In the other we say: "It is a compile-time error if at the end of the body of the compact constructor, any of the fields corresponding to the record components of R are neither definitely assigned nor definitely unassigned." Moreover, a deeper question: should we leave the magic auto-initialization of fields only for the compact form? That way, you would have a _new_ linguistic form, with _new_ properties, whereas old forms (e.g. a constructor with parameters) will have same rules as before (can have returns, must initialize fields explicitly). I think that, from a pedagogical aspect, that would be preferrable. Maurizio On 31/10/2019 14:17, Gavin Bierman wrote: > An updated draft language spec for JEP 359 (Records) is available at: > > http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html > > (Alongside is a draft JVM spec for this feature: > > http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html > > ) > > As always, please email me any comments/thoughts/bugs. > > Thanks, > Gavin > > >> On 23 Aug 2019, at 22:25, Gavin Bierman > > wrote: >> >> A draft language spec for records is available at: >> >> http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-jls.html >> >> This spec doesn?t yet discuss varargs records - to appear in the next >> draft. >> >> All comments welcomed! >> >> Thanks, >> Gavin > From maurizio.cimadamore at oracle.com Thu Oct 31 14:40:30 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 31 Oct 2019 14:40:30 +0000 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: Sorry, I think I was put off tracks by this: "The body of the canonical constructor must not contain a return statement (14.17)." Which appears on both compact and non-compact forms. I think non-compact constructors are just... constructors, so no additional rule/restriction should apply there? Maurizio On 31/10/2019 14:29, Maurizio Cimadamore wrote: > Moreover, a deeper question: should we leave the magic > auto-initialization of fields only for the compact form? That way, you > would have a _new_ linguistic form, with _new_ properties, whereas old > forms (e.g. a constructor with parameters) will have same rules as > before (can have returns, must initialize fields explicitly). I think > that, from a pedagogical aspect, that would be preferrable. From brian.goetz at oracle.com Thu Oct 31 14:51:41 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 31 Oct 2019 10:51:41 -0400 Subject: forbidding serialization methods as members of records In-Reply-To: <1a7f4011-379d-c5db-888b-b0a5fdb87af2@oracle.com> References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> <100FC279-D5A6-491A-9E09-AE05FE74E984@oracle.com> <956ded11-2de5-5bd1-491e-763863d0a4f4@oracle.com> <1a7f4011-379d-c5db-888b-b0a5fdb87af2@oracle.com> Message-ID: The language is somewhat schizoid about whether it errors or warns on useless constructs. (We error on unreachable code, for example.) And similarly, due to mistakes in 1997, the nature of serialization is somewhat schizoid ? it wants to be a library feature, but it really isn?t. So I think we?re justified here in giving either a warning or an error. > On Oct 31, 2019, at 10:15 AM, Maurizio Cimadamore wrote: > > > On 31/10/2019 14:09, Jonathan Gibbons wrote: >> >> On 10/31/19 5:25 AM, Chris Hegarty wrote: >>> >>>> On 31 Oct 2019, at 12:21, Vicente Romero wrote: >>>> >>>> Hi, >>>> >>>> In the past we discussed about forbidding the declaration of some serialization related methods in records. In particular: >>>> >>>> writeObject(ObjectOutputStream) >>>> readObjectNoData() >>>> readObject(ObjectInputStream) >>>> I wonder if we still want to enforce that restriction, meaning that it should be reflected in the spec, or if it is not necessary anymore, >>> Where we ended up with Serializable Records, is that the runtime is specified to ignore these methods if they appear in a serializable record ( there are tests that assert this ). The javac restriction is no longer strictly necessary, but of course catches effectively-useless declarations early, and without resorting checkers, inspection, etc. >>> >>> -Chris. >>> >> This seems to be in line with the general philosophy of the serialization specification in which candidate declarations for serialization-related members are ignored if they don't fulfill all the required properties. Without commenting on the merits of the policy, it would at least be good if the policy was consistent. Failing that, a warning (-Xlint:serial) would be in line with current javac behavior. > > I think we're talking about useless declarations - to me a warning is exactly the right fit for something like this. > > There's also a general desire to keep the JLS free from any jargon introduced by the serialization spec (and for a good reason). A warning gives us flexibility in that respect - an hard error doesn't (as the JLS will have to justify it). > > Maurizio > >> >> -- Jon From brian.goetz at oracle.com Thu Oct 31 15:29:28 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 31 Oct 2019 11:29:28 -0400 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: > "It is a compile-time error for a record declaration to declare a record component with the name |clone|, |finalize|, |getClass|, |hashCode|, |notify|, |notifyAll|, |readObjectNoData|, |readResolve|, |serialPersistentFields|, |serialVersionUID|, |toString|, |wait|, or |writeReplace|." > > Chris says that the serialization spec ignores all the serialization-related methods if they appear inside a record; should we lift the restrictions? But, I think we later decided we are not ignoring _all_ of the serialization-related methods ? that a readResolve() method is OK. I think there?s a difference between these two rules ? the one about component names clashing with serialization members, and the one about useless explicit serialization members. A badly named component could _implicitly_ give rise to a method that serialization might call ? which seems dangerous. Whereas a serialization member that never gets called is less so. So even if we are considering warnings for the latter category, I still think errors for this category is right. > "Every field corresponding to a record component of R must be definitely assigned and moreover not definitely unassigned (16.9) at the end of the body of the canonical constructor." > > In the other we say: > > "It is a compile-time error if at the end of the body of the compact constructor, any of the fields corresponding to the record components of R are neither definitely assigned nor definitely unassigned." > > Moreover, a deeper question: should we leave the magic auto-initialization of fields only for the compact form? That way, you would have a _new_ linguistic form, with _new_ properties, whereas old forms (e.g. a constructor with parameters) will have same rules as before (can have returns, must initialize fields explicitly). I think that, from a pedagogical aspect, that would be preferrable. Absolutely we should leave the new behavior (magic initialization) for the new form. A canonical constructor that is declared the old way should work like any other constructor. No magic initialization, no special requirements (the DA requirements of all constructors wrt final fields are all the safety we need), no stricture against return (which was there to avoid making the magic initialization more complicated. From joe.darcy at oracle.com Thu Oct 31 16:04:27 2019 From: joe.darcy at oracle.com (Joe Darcy) Date: Thu, 31 Oct 2019 09:04:27 -0700 Subject: forbidding serialization methods as members of records In-Reply-To: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> References: <93e10f72-05ef-9d3c-40e9-3df12529f3d9@oracle.com> Message-ID: <5aec300e-6163-8f98-2047-5252bdbdf8e9@oracle.com> Hello, Declaring a serialPersistentFields field should likely get the same warning/error treatment as the methods below. (The serialPersistentFields mechanism in serialization allows the set of serialized fields to be overridden.) Cheers, -Joe On 10/31/2019 5:21 AM, Vicente Romero wrote: > Hi, > > In the past we discussed about forbidding the declaration of some > serialization related methods in records. In particular: > > writeObject(ObjectOutputStream) > readObjectNoData() > readObject(ObjectInputStream) > > I wonder if we still want to enforce that restriction, meaning that it > should be reflected in the spec, or if it is not necessary anymore, > > Thanks, > Vicente > > From chris.hegarty at oracle.com Thu Oct 31 16:11:53 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Thu, 31 Oct 2019 16:11:53 +0000 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: <0E8032C5-19EE-41A1-9443-F363E210285C@oracle.com> > On 31 Oct 2019, at 15:29, Brian Goetz wrote: > >> "It is a compile-time error for a record declaration to declare a record component with the name |clone|, |finalize|, |getClass|, |hashCode|, |notify|, |notifyAll|, |readObjectNoData|, |readResolve|, |serialPersistentFields|, |serialVersionUID|, |toString|, |wait|, or |writeReplace|." >> >> Chris says that the serialization spec ignores all the serialization-related methods if they appear inside a record; should we lift the restrictions? > > But, I think we later decided we are not ignoring _all_ of the serialization-related methods ? that a readResolve() method is OK. FTR For records, the serialization runtime does consider the following: 1) writeReplace(), readResolve(), and 2) the serialVersionUID field The serialization runtime ignores the following: a) writeObject, writeObjectNoData, readObject, and b) serialPersistentFields, and c) writeExternal and readExternal - for what they?re worth! -Chris. From chris.hegarty at oracle.com Thu Oct 31 16:14:52 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Thu, 31 Oct 2019 16:14:52 +0000 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: > On 31 Oct 2019, at 15:29, Brian Goetz wrote: > > ... > I think there?s a difference between these two rules ? the one about component names clashing with serialization members, and the one about useless explicit serialization members. A badly named component could _implicitly_ give rise to a method that serialization might call ? which seems dangerous. Whereas a serialization member that never gets called is less so. So even if we are considering warnings for the latter category, I still think errors for this category is right. Agreed. -Chris. From forax at univ-mlv.fr Thu Oct 31 16:24:48 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 31 Oct 2019 17:24:48 +0100 (CET) Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> Message-ID: <2008037526.1327972.1572539088614.JavaMail.zimbra@u-pem.fr> > De: "Gavin Bierman" > ?: "amber-spec-experts" , "amber-dev" > > Envoy?: Jeudi 31 Octobre 2019 15:17:34 > Objet: Updated Draft specs for JEP 359 (Records) > An updated draft language spec for JEP 359 (Records) is available at: > [ > http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html > | > http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html > ] > (Alongside is a draft JVM spec for this feature: > [ > http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html > | > http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html > ] > ) I've read the JVMS draft, it's ok for me. I still think that not supporting @Deprecated on a record component is a mistake. Both Scala [1] and C# support deprecating ""property"", so we know that there is a need. And let's not forget that at some point in the future, Scala or Kotlin may want to retrofit their case class/data class to record when possible to have a better Java integration. > As always, please email me any comments/thoughts/bugs. regards, R?mi > Thanks, > Gavin [1] https://stackoverflow.com/questions/49385374/is-actually-possible-to-deprecate-scala-case-class-fields >> On 23 Aug 2019, at 22:25, Gavin Bierman < [ mailto:gavin.bierman at oracle.com | >> gavin.bierman at oracle.com ] > wrote: >> A draft language spec for records is available at: >> [ >> http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-jls.html >> | >> http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-jls.html >> ] >> This spec doesn?t yet discuss varargs records - to appear in the next draft. >> All comments welcomed! >> Thanks, >> Gavin From maurizio.cimadamore at oracle.com Thu Oct 31 17:14:56 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 31 Oct 2019 17:14:56 +0000 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: <0E8032C5-19EE-41A1-9443-F363E210285C@oracle.com> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <0E8032C5-19EE-41A1-9443-F363E210285C@oracle.com> Message-ID: <4bb7e883-2080-ac87-d58e-31851216427d@oracle.com> On 31/10/2019 16:11, Chris Hegarty wrote: > >> On 31 Oct 2019, at 15:29, Brian Goetz wrote: >> >>> "It is a compile-time error for a record declaration to declare a record component with the name |clone|, |finalize|, |getClass|, |hashCode|, |notify|, |notifyAll|, |readObjectNoData|, |readResolve|, |serialPersistentFields|, |serialVersionUID|, |toString|, |wait|, or |writeReplace|." >>> >>> Chris says that the serialization spec ignores all the serialization-related methods if they appear inside a record; should we lift the restrictions? >> But, I think we later decided we are not ignoring _all_ of the serialization-related methods ? that a readResolve() method is OK. > > FTR > > For records, the serialization runtime does consider the following: > > 1) writeReplace(), readResolve(), and > 2) the serialVersionUID field > > The serialization runtime ignores the following: > > a) writeObject, writeObjectNoData, readObject, and > b) serialPersistentFields, and > c) writeExternal and readExternal - for what they?re worth! Ok, so, error on (1) and (2) and warnings in all the other cases? Maurizio > > -Chris. From chris.hegarty at oracle.com Thu Oct 31 20:10:49 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Thu, 31 Oct 2019 20:10:49 +0000 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: <4bb7e883-2080-ac87-d58e-31851216427d@oracle.com> References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <0E8032C5-19EE-41A1-9443-F363E210285C@oracle.com> <4bb7e883-2080-ac87-d58e-31851216427d@oracle.com> Message-ID: > On 31 Oct 2019, at 17:14, Maurizio Cimadamore wrote: > > > On 31/10/2019 16:11, Chris Hegarty wrote: >> >>> On 31 Oct 2019, at 15:29, Brian Goetz wrote: >>> >>>> "It is a compile-time error for a record declaration to declare a record component with the name |clone|, |finalize|, |getClass|, |hashCode|, |notify|, |notifyAll|, |readObjectNoData|, |readResolve|, |serialPersistentFields|, |serialVersionUID|, |toString|, |wait|, or |writeReplace|." >>>> >>>> Chris says that the serialization spec ignores all the serialization-related methods if they appear inside a record; should we lift the restrictions? >>> But, I think we later decided we are not ignoring _all_ of the serialization-related methods ? that a readResolve() method is OK. >> >> FTR >> >> For records, the serialization runtime does consider the following: >> >> 1) writeReplace(), readResolve(), and >> 2) the serialVersionUID field >> >> The serialization runtime ignores the following: >> >> a) writeObject, writeObjectNoData, readObject, and >> b) serialPersistentFields, and >> c) writeExternal and readExternal - for what they?re worth! > > Ok, so, error on (1) and (2) and warnings in all the other cases? In terms of restrictions on record component name... - 1 and 2 should be errors - I think that a, b, and c, should probably be errors too. It would be super confusing to the reader to see component, field, accessors, names with such names. But if not errors, warnings would be good. In terms of javac restrictions in the record declaration? - 1 and 2 much be allowable, no issue - a, b, and c, should be lint warnings. -Chris. From chris.hegarty at oracle.com Thu Oct 31 20:25:56 2019 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Thu, 31 Oct 2019 20:25:56 +0000 Subject: Updated Draft specs for JEP 359 (Records) In-Reply-To: References: <146C0891-97B3-4DBD-AA10-CCD485357BA2@oracle.com> <0E8032C5-19EE-41A1-9443-F363E210285C@oracle.com> <4bb7e883-2080-ac87-d58e-31851216427d@oracle.com> Message-ID: > On 31 Oct 2019, at 20:10, Chris Hegarty wrote: > >> ... > > > In terms of javac restrictions in the record declaration? To be clear, javac restrictions *of methods and fields*, in the record declaration? > - 1 and 2 much be allowable, no issue > - a, b, and c, should be lint warnings. > > -Chris.