Cannot compare object.opEquals is not nogc

Jonathan Marler via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Jul 23 09:46:20 PDT 2016


On Saturday, 23 July 2016 at 15:25:02 UTC, Steven Schveighoffer 
wrote:
> On 7/23/16 10:53 AM, Rufus Smith wrote:
>> On Saturday, 23 July 2016 at 14:15:03 UTC, Lodovico Giaretta 
>> wrote:
>>> On Saturday, 23 July 2016 at 13:18:03 UTC, Rufus Smith wrote:
>>>> Trying to compare a *ptr value with a value in nogc code 
>>>> results in
>>>> the error:
>>>>
>>>> Error: @nogc function '...' cannot call non- at nogc function
>>>> 'object.opEquals'
>>>>
>>>> Shouldn't object opEquals be marked?
>>>
>>> If object.opEquals is marked @nogc, than all D classes must 
>>> implement
>>> it as @nogc, because (of course) you cannot override a @nogc 
>>> method
>>> with a not- at nogc one (while the opposite is possible, of 
>>> course).
>>> So marking it @nogc is not only a big breaking change, but 
>>> also very
>>> limiting.
>>
>> Um, this isn't right. GC code can always call non-gc code.
>
> The issue is that for *classes*, the proper way to add an 
> opEquals is to override the base version. The base version 
> existed LONG before @nogc did, and so it's not appropriately 
> marked.
>
> Not only that, but @nogc is too limiting (if I want to use GC 
> in opEquals, I should be able to).
>
> The real problem here is that there is a base method at all. We 
> have been striving to remove it at some point, but it is very 
> difficult due to all the legacy code which is written.
>
> Almost all the Object base methods need to be removed IMO. You 
> can add them at a higher level if you need them, and then 
> specify your requirements for derived classes.
>
> Including opHash, opCmp, toString, etc.
>
>> If you mark opEquals nogc, it breaks nothing except 
>> implementations of
>> opEquals that use the GC. GC code can still call it nogc 
>> opequals, it
>> only enforces opEquals code to avoid the GC itself, which 
>> isn't a
>> terrible thing.
>
> It breaks all classes which use GC in opEquals. Note that you 
> can't really compare two immutable or const objects either! 
> (well, actually you can, but that's because the runtime just 
> casts away const and lets you have undefined behavior).
>
>> What is terrible is that nogc code can never have any equality
>> comparisons! It is impossible unless one manually tests them, 
>> but how?
>> Every method would be brittle. Do a memory test? compare 
>> element by
>> element? One can't predict what to do.
>
> It is unfortunate. I hope we can fix it. I'd rather not add 
> another exception like we have for comparing const objects.
>
>> So, you are trying off laziness to break nogc. As it stands, 
>> if nogc
>> code can't compare equality, it is broken and useless. Why put 
>> it in the
>> language then?
>
> @nogc is not useless, it just cannot handle Objects at the 
> moment.
>
>> Broke! Even if opEquals of T does not use any GC we can't 
>> write test to
>> be nogc, which means we can't have S be nogc or anything that 
>> depends on
>> S that is nogc. This must be a dirty trick played by the 
>> implementors of
>> nogc to keep everyone on the gc nipple?
>
> I assure you, it's not a trick. It's legacy. It needs fixing, 
> but the fix isn't painless or easy.
>
> -Steve

I've seen this type of problem many times before when using the 
@nogc attribute.  With alot of work, and breaking changes, you 
could fix it in the case of opEquals, and in the end you still 
end up with the restriction that you can't use the GC in 
opEquals, which may be a good thing, but some would disagree.  
But this is a common problem and I think a more exhaustive 
solution would be to allow @nogc code to call that that is either 
marked as nogc, or inferred to be @nogc.  Instead of treating 
@nogc as a special compiler directive to check for GC code, the 
compiler could check for GC code in all cases, and infer the 
attribute for all functions.  Then @nogc would simply be a way 
for the developer to tell the compiler to make sure they aren't 
using @nogc where they don't intend to.  This allows code that is 
written without @nogc to be called from code that does use it.  
It takes an effort away from the developer and moves it to the 
compiler.  It allows @nogc to work with existing code.

Maybe this would result in a big performance hit on the compiler 
because now it would always have to check for GC code, instead of 
just when it's specified with @nogc...not sure.

Anyway, this is just a general overview.  There's obviously alot 
of details and specifics that were glossed over but I think the 
general idea could be a good solution.


More information about the Digitalmars-d-learn mailing list