<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Brian Goetz" <brian.goetz@oracle.com><br><b>To: </b>"attila kelemen85" <attila.kelemen85@gmail.com><br><b>Cc: </b>"amber-dev" <amber-dev@openjdk.org>, "Gavin Bierman" <gavin.bierman@oracle.com><br><b>Sent: </b>Tuesday, April 23, 2024 3:34:16 PM<br><b>Subject: </b>Re: New candidate JEP: 468: Derived Record Creation (Preview)</blockquote><div><br></div><div>[promoted to amber-spec-expert because I think this discussion is quite interresting]<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
So, a further thing to keep in mind is that currently, adding fields to records is not even source compatible to begin with.  For example, if we have
<div class=""><br class="">
</div>
<div class="">    record Point(int x, int y) { }</div>
<div class=""><br class="">
</div>
<div class="">And a client uses it in a pattern match:</div>
<div class=""><br class="">
</div>
<div class="">    case Point(int x, int y): </div>
<div class=""><br class="">
</div>
<div class="">And then we add an `int z` component, the client will break.  (When we are able to declare deconstruction patterns, such a migration could include an XY pattern as well as constructor, but we are not there yet.)  </div>
<div class=""><br class="">
</div>
<div class="">I think your mail rests on the assumption that it should be fine to modify records willy-nilly and expect compatibility without a recompile-the-world, but I think this is a questionable assumption.</div></blockquote><div><br></div><div>This is a reasonable assumption. Java is well know to be backward compatible, people will expect any new feature to be backward compatible too.</div><div>As an example, the way enums were compiled in 1.5 was not bacward compatible if the enums were used in a switch. Later the translation strategy was changed to be backward compatible.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div><div>One possible quick fix is to restrict the access. For sealed classes, we have restricted the permitted subclasses to be in the same package/same module to avoid such separate compilation issues.</div><div><br></div><div>Do you think that introducing the same restriction on derived record creation is a good idea ?</div></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div class="">  Records will likely have features that ordinary
 classes do not yet have access to for a while, making such changes risky.  </div></blockquote><div><br data-mce-bogus="1"></div>Yes, the idea of derived record creation is based on the fact that there is a canonical constructor + a way to deconstruct using accessors (for now).</div><div data-marker="__QUOTED_TEXT__">I do not see classes having canonical constructors in the future so yes, this feature is limited to records.</div><div data-marker="__QUOTED_TEXT__"><div><br data-mce-bogus="1"></div><div>RĂ©mi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div class=""><br class="">
<div><br class="">
<blockquote class="">
<div class="">On Apr 20, 2024, at 5:49 PM, Attila Kelemen <<a href="mailto:attila.kelemen85@gmail.com" class="" target="_blank">attila.kelemen85@gmail.com</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div dir="ltr" class="">I have a backward compatibility concern about this JEP. Consider that I have the following record:
<div class=""><br class="">
</div>
<div class="">`record MyRecord(int x, int y) { }`<br class="">
</div>
<div class=""><br class="">
</div>
<div class="">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:</div>
<div class=""><br class="">
</div>
<div class="">```<br class="">
record MyRecord(int x, int y, int z) {<br class="">
    public MyRecord(int x, int y) {<br class="">
        this(x, y, 0);<br class="">
    }<br class="">
}<br class="">
```<br class="">
</div>
<div class=""><br class="">
</div>
<div class="">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:</div>
<div class=""><br class="">
</div>
<div class="">```</div>
<div class="">var obj1 = new MyRecord(1, 2);<br class="">
int z = 26;<br class="">
var obj2 = obj1 with { y = z; }<br class="">
</div>
<div class="">```</div>
<div class=""><br class="">
</div>
<div class="">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.</div>
<div class=""><br class="">
</div>
<div class="">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.</div>
<div class=""><br class="">
</div>
<div class="">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.</div>
<div class=""><br class="">
</div>
<div class="">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.</div>
<div class=""><br class="">
</div>
<div class="">Attila</div></div></div></blockquote></div></div></blockquote><div><br></div><div><br></div></div></div></body></html>