Thread overview
immutable class can't override opEquals, workaround?
Feb 21, 2016
SimonN
Feb 21, 2016
Jonathan M Davis
Feb 22, 2016
SimonN
February 21, 2016
Hi,

    immutable class A {
        int i;
        this(int arg) { i = arg; }
        override bool opEquals(Object rhsObj)
        {
            auto rhs = cast (immutable(A)) rhsObj;
            return rhs && i == rhs.i;
        }
    }

Error by dmd 2.070:

    ./immutclass.d(4): Error: function immutclass.A.opEquals
    does not override any function, did you mean to override
    'object.Object.opEquals'?

My understandings:

1.  immutable class A means: All methods have immutable tacked
    on them implicitly.
2.  Object.opEquals doesn't have immutable tacked on it. If I
    want to override Object.opEquals, I should override without
    'immutable'.
3.  Overriding opEquals and toHash are necessary to make A
    behave properly as AA key type. This is incompatible with
    (2) in an immutable class.
4.  I found this thread:
        How to turn an inout(Object) into a string
        http://forum.dlang.org/thread/dcobmtogyrmnaqnqyvbz@forum.dlang.org
    that I interpret as: The need for the currently-impossible
    override is acknowledged, but the implementation would bring
    significant changes to the language, therefore the solution
    is postponed. The above thread was from mid-2015, but I guess
    it's still relevant.

My workaround is: Make class _A private, and declare every method
immutable, except for what Object decrees to be mutable/const/...
Then make a public alias A = immutable(_A).

Is there something better than this?

Has there been any new development on Object method removal?
Jonathan M Davis has been pushing this hard 2 years ago, I'd
love to see the efforts make it into the language. :-)

-- Simon
February 20, 2016
On Sunday, February 21, 2016 04:25:59 SimonN via Digitalmars-d-learn wrote:
> Hi,
>
>      immutable class A {
>          int i;
>          this(int arg) { i = arg; }
>          override bool opEquals(Object rhsObj)
>          {
>              auto rhs = cast (immutable(A)) rhsObj;
>              return rhs && i == rhs.i;
>          }
>      }
>
> Error by dmd 2.070:
>
>      ./immutclass.d(4): Error: function immutclass.A.opEquals
>      does not override any function, did you mean to override
>      'object.Object.opEquals'?
>
> My understandings:
>
> 1.  immutable class A means: All methods have immutable tacked
>      on them implicitly.
> 2.  Object.opEquals doesn't have immutable tacked on it. If I
>      want to override Object.opEquals, I should override without
>      'immutable'.
> 3.  Overriding opEquals and toHash are necessary to make A
>      behave properly as AA key type. This is incompatible with
>      (2) in an immutable class.
> 4.  I found this thread:
>          How to turn an inout(Object) into a string
>
> http://forum.dlang.org/thread/dcobmtogyrmnaqnqyvbz@forum.dlang.org
>      that I interpret as: The need for the currently-impossible
>      override is acknowledged, but the implementation would bring
>      significant changes to the language, therefore the solution
>      is postponed. The above thread was from mid-2015, but I guess
>      it's still relevant.
>
> My workaround is: Make class _A private, and declare every method immutable, except for what Object decrees to be mutable/const/... Then make a public alias A = immutable(_A).
>
> Is there something better than this?
>
> Has there been any new development on Object method removal? Jonathan M Davis has been pushing this hard 2 years ago, I'd love to see the efforts make it into the language. :-)

Okay. Until opEquals, toHash, toString, and opCmp have been removed from Object, you can't override any of them as anything other than mutable. opEquals still works with const and immutable objects via a hack in druntime (it casts away const inside of the free function opEquals which works if your opEquals behaves but results in undefined behavior if it mutates anything). So, I expect that it's simply not possible right now to use a class as a key in an AA, though a struct should work if it's defined appropriately. Certainly, if it's legal to use a class as the key in an AA, it's a bug given that there's no guarantee that it's immutable like a key needs to be.

As for actually getting rid of opEquals and friends from Object, no real progress has been made. I finally have a working version of the PR to templatize the free function opEquals such that it will work with opEquals that take a derived class instead of Object (previously, compiler bugs kept getting in the way of it working), but it hasn't even been looked at yet from what I can tell, and it's the simplest of the bits that need to be done (https://github.com/D-Programming-Language/druntime/pull/1439). The overhaul of the AA implementation to templatize it needs to be completed (and I'm not sure where it currently stands) and there will likely have to be some clever compiler changes to make it so that we can remove those 4 functions from Object without breaking code in the process. So, it's going to take a variety of people to get it done, and unfortunately, it hasn't been high on much of anyone's todo list.

- Jonathan M Davis

February 22, 2016
On Sunday, 21 February 2016 at 07:58:42 UTC, Jonathan M Davis wrote:
> opEquals still works with const and immutable
> if it's legal to use a class as the key in an AA, it's a bug

> have a working version of the PR
> hasn't even been looked at yet from what I can tell,
> and it's the simplest of the bits that need to be done

Thanks for the detailed overview.

Judging from the source comment at hack-casting const to mutable, naive improvements affect much more code than I have imagined.

The problem and possible solutions are on the radar still, that's satisfying. I understand if it takes more time, even if I too deem it important.

-- Simon