how to make '==' safe for classes?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Oct 28 19:00:52 UTC 2018


On Sunday, October 28, 2018 6:38:12 AM MDT ikod via Digitalmars-d-learn 
wrote:
> Hello
>
> How to make this code to compile? My goal is safe(not @trusted)
> longFunction().
>
>
> ---
> class C
> {
>      override bool opEquals(Object o) const @safe
>      {
>          return true;
>      }
> }
> bool longFunction(C a, C b) @safe
> {
>      return a==b;
> }
> void main()
> {
> }
> ---
>
>
> As far as I understand the problem is that AST for this code
> looks like
>
> ---
> import object;
> class C : Object
> {
>   override const @safe bool opEquals(Object o)
>   {
>       return true;
>   }
> }
> bool longFunction(C a, C b)
> {
>   return opEquals(a, b);
> }
> void main()
> {
>   return 0;
> }
> RTInfo!(C)
> {
>   enum typeof(null) RTInfo = null;
>
> }
> ---
>
> and object.opEquals(a,b) do not inherits safety from class C
> properties, and also I can't override it.
>
> Is there clean way to use '==' here, or I have to convert this to
> a.opEquals(b) for classes, leaving '==' for structs?
>
> Thanks!

Because Object predats @safe (and most attributes), it really isn't
compatible with them. In fact, it predates const (since it's basically the
same as it was in D1) and it's only possible to compare const class objects
because of a hack in the free function opEquals (which == lowers to) which
casts away const (meaning that if you're not careful, you can actually
violate the type system with == by mutating an object in a class' opEquals).
And because attributes are inherited, even if we were willing to break
existing code by changing the attributes on Object, there really isn't a
good way to fix the problem, because whatever set of attributes we picked
(for @safe, nothrow, const, etc.) would work for some programs but not
others. That's why at one point, it was decided that we would remove all of
the various member functions from Object. Given the templates in D, they
really aren't necessary like they are in languages like Java. As long as
stuff like the built in AA implementation is templated (which it
unfortunately is not right now), all of the appropriate information can be
inferred, and it's not necessary to have a root class object with member
functions like opEquals in order to use it in generic code.

https://issues.dlang.org/show_bug.cgi?id=9769
https://issues.dlang.org/show_bug.cgi?id=9770
https://issues.dlang.org/show_bug.cgi?id=9771
https://issues.dlang.org/show_bug.cgi?id=9772

However, while that decision was made some time ago, actually implementing
it isn't easy, and the necessary steps have never happened - to the point
that it doesn't seem very likely at this point. What seems far more likely
is a DIP that Andrei has proposed:

https://github.com/andralex/DIPs/blob/ProtoObject/DIPs/DIPxxxx.md

It will introduce ProtoObject as a new root object below Object which does
not have any member functions or an embedded monitor object (which is only
necessary if you actually have synchronized functions). Object would stay
the default base class (since code would break otherwise), and any code
using Object would unfortunately continue to have the same problems, but
classes that then explicitly derive from ProtoObject would be able to define
opEquals, opCmp, toString, etc. with the signatures that were appropriate to
the applications or libraries that they're in. Any classes derived from such
classes would then be stuck with those attributes just like we're stuck with
the attributes on Object right now, but those choices would then be per
object hierarchy rather than forced on everyone using the language. So, it
looks like that's probably going to be the ultimate fix for this problem,
but we don't really have an ETA at the moment.

So, unfortunately, for now, you're going to have to use @trusted with == on
classes, as stupid as that is, though as a workaround, you could always
create an @trusted wrapper function that just called ==. It would still be
annoying, but it would be cleanly restricted the @trusted bits.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list