De: "John Rose" <john.r.rose@oracle.com> À: "Remi Forax" <forax@univ-mlv.fr> Cc: "Peter Levart" <peter.levart@gmail.com>, "Rémi Forax" <forax@openjdk.java.net>, "core-libs-dev" <core-libs-dev@openjdk.java.net> Envoyé: Vendredi 4 Juin 2021 02:05:41 Objet: Re: [External] : Re: RFR: 8199318: add idempotent copy operation for Map.Entry
On Jun 3, 2021, at 3:17 PM, [ mailto:forax@univ-mlv.fr | forax@univ-mlv.fr ] wrote:
De: "John Rose" <john. [ mailto:r.rose@oracle.com | r.rose@oracle.com ] > À: "Remi Forax" < [ mailto:forax@univ-mlv.fr | forax@univ-mlv.fr ] > Cc: "Peter Levart" < [ mailto:peter.levart@gmail.com | peter.levart@gmail.com ]
, "Rémi Forax" < [ mailto:forax@openjdk.java.net | forax@openjdk.java.net ] >, "core-libs-dev" < [ mailto:core-libs-dev@openjdk.java.net | core-libs-dev@openjdk.java.net ] > Envoyé: Jeudi 3 Juin 2021 22:51:28 Objet: Re: RFR: 8199318: add idempotent copy operation for Map.Entry
...
interface ComparableRecord<T extends Record & ComparableRecord<T>> extends Comparable<T> { … }
record Foo(int x, String y) implements ComparableRecord<Foo> { … }
[ http://cr.openjdk.java.net/~jrose/draft/ComparableRecord.java | http://cr.openjdk.java.net/~jrose/draft/ComparableRecord.java ]
[repost with a link]
The main issue with this kind of code is that the JIT does not see through the ClassValue.
Wow, it’s almost as if we’ve discussed this already! ;-) So, [ https://bugs.openjdk.java.net/browse/JDK-8238260 | https://bugs.openjdk.java.net/browse/JDK-8238260 ] Part of my agenda here is finding more reasons why JDK-8238260 deserves some love.
Currently, the translation strategy for Records requires a lot of boilerplate generated into each subclass for toString, equals, and hashCode. It is partially declarative, because it uses indy. So, yay for that. But it is also a bad smell (IMO) that the trick needs to be played in each subclass.
If ClassValue were performant, we could have just one method in Record for each of toString, equals, and hashCode, and have them DTRT. The user code would then be able to call super.toString() to get the standard behavior in a refining wrapper method in a subclass.
Looking further, it would be nice to have methods which (a) inherit from supers as reusable code ought to, but (b) re-specialize themselves once per subclass indy-style. This is a VM trick I hope to look into after we do specialization. For now, ClassValue is the way to simulate that.
yes, it's a specialization problem. I wonder if it an be resolved using a combination of a species-static variable and magic shibboleth to ask the type parameter to be always reified interface ComparableRecord <please-always-reified-me T extends Record & ComparableRecord< T > > extends Comparable< T > { species-static Comparator<T> COMPARATOR; // a parameteric condy ? species-static { COMPARATOR = ... } default int compareTo(T other) { return COMPARATOR.compare(this, other); } }
Tweaking a little bit your code, I get [ https://urldefense.com/v3/__https://gist.github.com/forax/e76367e1a90bf01169... | https://gist.github.com/forax/e76367e1a90bf011692ee9bec65ff0f8 ]
(It's a PITA that we have to use a raw type to workaround circularly defined parameter type)
I tried to DTRT and got into Inference Hell, surrounded by a swarms of unfriendly wildcards with pitchforks. Glad it wasn’t just me.
Inspired by your more whole-hearted use of streams to build the code, I updated my example. Thanks.
— John
Rémi