[datum] initial public push (IPP)

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Nov 9 18:22:35 UTC 2017

On 09/11/17 17:41, Robert Gibson wrote:
> The idea is to remove the possibility of ‘always false’ equals comparisons “Hello”.equals(3) for data classes.  Your IDE might currently warn about them, but can we do better?
> The simplest approach is just
> __data class Point(int x, int y);
> // implies public boolean equals(Point p), maybe with a bridge method from equals(Object o)
> Point p = new Point(1, 2);
> assert p.equals(new Point(1, 2));
> // Doesn’t compile, hooray!
> //assert !p.equals(“point”);
> But that very quickly runs into problems
> // Oops, we lost transitivity
> assert !”point”.equals(p);
> Object o = p;
> // Oops, we got a ClassCastException (probably)
> assert !o.equals(“point”);
I guess it depends on how you generate the bridge - one way would be to 
emit a bridge that does this:

**synthetic** boolean equals(Object o) {
if (o instanceof Point) {
    return equals((Point)o);
} else {
    return false;

In which case there's no CCE - but the compiler would still bark when 
trying to do equals("Hello!") on a Point (because of the stricter 
> And there are more pitfalls of course around inheritance, although the rule of “only one concrete class in a hierarchy” eases the pain a little.
Not sure about this. On the one hand, under the current proposal, only 
concrete datum (leaves in the hierarchy) get an equals method. So you 
could just say that the stricter equals and the associated bridge is 
only generated on such leaves. But that leaves out cases like these:

abstract datum AbstractPoint(int x, int y);

datum Point(int x, int y) extends AbstractPoint(x, y);

Point p = ...
p.equals(""); //error
((AbstractPoint)p).equals(""); // ok?

And if we want the last statement above to be an error, does it mean we 
have to generate an equals(AbstractDatum) on the intermediate leave? 
Maybe. But then:

AbstractPoint ap = ...
Point p = ...
p.equals(ap); //error
((AbstractPoint)p).equals(ap); // ok?

Seems can-of-wormey...

> I suspect that backwards compatibility is going to win out pretty quickly (for example, Scala case classes and Kotlin data classes both define equals in terms of Any), but I note that C# records implement IEquatable<T>, an interface which has ‘only’ existed since C# 2.0
> I’m just interested to know if you have done any exploration of this space, or if it is completely out of scope and off the radar (to mix my metaphors a little)?
> Thanks,
> Robert
>> On 9 Nov 2017, at 18:02, Vicente Romero <vicente.romero at oracle.com> wrote:
>> Hi Robert,
>> On 11/09/2017 11:40 AM, Robert Gibson wrote:
>>> Hi,
>>> This looks promising.  I read Brian’s note [1] and I wondered if you have given any consideration to the idea of attempting to generify the equals() method for data classes?
>> Interesting question, we haven't spoken about it. Could you please provide a test case for this feature?
>>> Thanks,
>>> Robert
>> Thanks,
>> Vicente
>>> http://cr.openjdk.java.net/~briangoetz/amber/datum.html
>>>> On 8 Nov 2017, at 12:28, amber-dev-request at openjdk.java.net wrote:
>>>> Date: Tue, 7 Nov 2017 13:11:40 -0500
>>>> From: Vicente Romero <vicente.romero at oracle.com>
>>>> To: Amber dev <amber-dev at openjdk.java.net>
>>>> Subject: [datum] initial public push (IPP)
>>>> Message-ID: <a00cffb6-217b-7e04-ffd3-37f51934352e at oracle.com>
>>>> Content-Type: text/plain; charset=utf-8; format=flowed
>>>> Hi all,
>>>> We have just made public the development of data classes [1]. The
>>>> development will continue in the "datum" branch in the amber repo [2].
>>>> Data classes allow for more compact class declarations. Basically for
>>>> classes for which the state of the class can be declared in the class
>>>> header. The basic, informal, data class syntax is:
>>>> ? __datum Name(Fields) { BODY } or for a body-less data class:
>>>> ??? __datum Name(Fields);
>>>> here Fields is a list of fields, and each field can be:
>>>> [@Annos] [ __nonfinal ] type name
>>>> *Note:* __datum and __nonfinal are just place holders, the final keyword
>>>> to be used is still to be defined
>>>> The fields are implicitly lifted onto fields of the class, with the
>>>> default accessibility of "package final", unless noted as non-final. Any
>>>> additional field declarations in the body are prohibited. Non-abstract
>>>> data classes are final. Data classes can be generic and can implement
>>>> arbitrary interfaces. Every non-abstract data class acquires:
>>>> ?- a public constructor that takes fields in the order specified by the
>>>> field list, and initializes all fields;
>>>> ?- public getters for each field, whose name is same as the field;
>>>> ?- public equals(), hashCode(), and toString().
>>>> If the user provides any of the above members explicitly, it will be
>>>> used instead of the default defined by the compiler. Abstract data
>>>> classes are permitted; but they get only a public constructor.? By
>>>> default the field access of abstract data classes is protected and they
>>>> are final.? In addition, data classes can extend abstract data classes.?
>>>> Also, data classes with no parent class have the new class
>>>> java.lang.DataClass as its parent.? Extension looks like:
>>>> abstract __datum X(int x);
>>>> ??? __datum Y(int x, int y) extends X(int x);
>>>> that is, the fields of X must be a proper prefix (arity, name, and
>>>> types) of Y's fields. For example the compiler won't accept this
>>>> declaration for Bad data class:
>>>> ??? abstract __datum Sup(int x, int y);
>>>> ??? __datum Bad(int x, int y, int z) extends Sup(x, z); // field name
>>>> mismatch should be Sup(x, y)
>>>> The current implementation doesn't allow data classes with an empty list
>>>> of fields, so:
>>>> ??? __datum D2();? // compiler error
>>>> we can relax this constraint in the future if there are sensible use
>>>> cases for which it makes sense to declare an empty data class.
>>>> Please try it out and get back to us with your feedback!
>>>> Thanks,
>>>> Vicente
>>>> PS. this code is under active development and bugs are being chased out
>>>> but still lurking, thanks a lot in advance for any bug report!
>>>> [1] http://hg.openjdk.java.net/amber/amber/rev/04260073c6bd
>>>> [2] http://hg.openjdk.java.net/amber/amber

More information about the amber-dev mailing list