Object.toString, toHash, opCmp, opEquals

Quirin Schroll qs.il.paperinik at gmail.com
Thu Jun 6 09:57:29 UTC 2024


On Thursday, 6 June 2024 at 08:00:40 UTC, Ogi wrote:
> On Wednesday, 5 June 2024 at 17:42:20 UTC, Quirin Schroll wrote:
>> except for `toString`
>
> Well, we could make it compatible with @nogc:
> ```D
> void toString(scope void delegate(in char[]) pure nothrow @nogc 
> sink) const scope pure nothrow @nogc
> ```

That’s actually a big no. Such a `toString` can’t be used e.g. to 
append the characters to an array as that’s not a `@nogc` sink.

You need 16 overloads, all but 1 of them `final`, the non-`final` 
one without attributes. Then, derived classes could override the 
non-attributed version where the attributed versions (the `final` 
ones in `Object`) call the overridable one and do a little 
casting so that it’s possible. This sounds great on first glance, 
but the issue here is that this approach assumes that the 
`toString` implementation is essentially compatible with all 
attributes except for the `sink` call. While the default 
implementation in `Object` can have this property, overriders may 
not be, and if they’re not, there’s no error (or warning).

In cases like `opApply`, that approach works, but only because 
one can statically know that the implementation will respect 
attributes. For classes, due to overriding, one cannot.

What would be needed is a notion of attribute variables, similar 
to how `inout` is a type qualifier variable. Then,
```d
void toString(scope void delegate(in char[]) xpure xnothrow 
@xnogc sink) const scope xpure xnothrow @xnogc;
```
makes sense. Overriders would be bound to the same relative 
respect to attributes.

The correct choice is a template, but templates cannot be virtual.


More information about the Digitalmars-d mailing list