New candidate JEP: 468: Derived Record Creation (Preview)

Remi Forax forax at univ-mlv.fr
Sat Apr 20 17:30:14 UTC 2024


> From: "attila kelemen85" <attila.kelemen85 at gmail.com>
> To: "amber-dev" <amber-dev at openjdk.org>
> Cc: "Gavin Bierman" <gavin.bierman at oracle.com>, "jdk-dev" <jdk-dev at openjdk.org>
> Sent: Saturday, April 20, 2024 5:49:22 PM
> Subject: Re: New candidate JEP: 468: Derived Record Creation (Preview)

> I have a backward compatibility concern about this JEP. Consider that I have the
> following record:
> `record MyRecord(int x, int y) { }`

> One day I realize that I need that 3rd property which I want to add in a
> backward compatible way, which I will do the following way:

> ```
> record MyRecord(int x, int y, int z) {
> public MyRecord(int x, int y) {
> this(x, y, 0);
> }
> }
> ```

> As far as I understand, this will still remain binary compatible. However, if I
> didn't miss anything, then this JEP makes it non-source compatible, because
> someone might wrote the following code:

> ```
> var obj1 = new MyRecord(1, 2);
> int z = 26;
> var obj2 = obj1 with { y = z; }
> ```

> If this code is compiled again, then it will compile without error, but while in
> the first version `obj2.y == 26`, now `obj2.y == 0`. This seems rather nasty to
> me because I was once bitten by this in Gradle (I can't recall if it was Groovy
> or Kotlin, but it doesn't really matter), where this is a threat, and you have
> to be very careful adding a new property in plugin extensions with a too
> generic name. Even though Gradle scripts are far less prone to this, since
> those scripts are usually a lot less complicated than normal code.

> I saw in the JEP that on the left hand side of the assignment this issue can't
> happen, but as far as I can see the above problem is not prevented.

> My proposal would be to, instead of shadowing variables, raise a compile time
> error when the property name would shadow another variable. Though that still
> leaves the above example backward incompatible, but at least I would be
> notified of it by the compiler, instead of the compiler silently creating a
> bug.

> Another solution would be that the shadowing is done in the opposite order, and
> the `int z = 26;` shadows the record property (with a potential warning). In
> this case it would be even source compatible, if I didn't miss something.

> Attila

Hello, i think you are pre-supposing a specific compiler translation strategy, but it can be compiled like this: 

MyRecord obj1 = new MyRecord(1, 2); 
int z = 26; 

Object carrier = indy(r); // create a carrier object by calling all the accessors 
// so the side effects are done before calling the block 
int y = z; 
MyRecord obj2 = indy(carrier, /*y:*/ y); // create an instance of MyRecord using 'y' and the values in the carrier 

With the carrier instances working like https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/runtime/Carriers.java 

regards, 
Rémi 

> Mark Reinhold < [ mailto:mark.reinhold at oracle.com | mark.reinhold at oracle.com ] >
> ezt írta (időpont: 2024. febr. 28., Sze, 21:04):

>> [ https://openjdk.org/jeps/468 | https://openjdk.org/jeps/468 ]

>> Summary: Enhance the Java language with derived creation for
>> records. Records are immutable objects, so developers frequently create
>> new records from old records to model new data. Derived creation
>> streamlines code by deriving a new record from an existing record,
>> specifying only the components that are different. This is a preview
>> language feature.

>> - Mark
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/jdk-dev/attachments/20240420/c973ab62/attachment.htm>


More information about the jdk-dev mailing list