What to do when you want to add attributes to your class functions?

RazvanN razvan.nitu1305 at gmail.com
Fri Sep 16 09:25:58 UTC 2022


Let's say you have a library class that exposes some methods. At 
the beginning you did not focus on the safety, nogcness etc. of 
your methods, you just wanted to have something working. You 
publish your class, people start using it and now you are in a 
phase where you would like your methods to be callable from 
attributed contexts. So you go on and make your code safe, 
nothrow, nogc, pure. However, now you are faced with a large 
breaking change because suddenly you force your users to respect 
these attributes. This seems like a severe limitation to me. 
Morever, look at this code:

```d
class Test
{
     void fun() @safe {}
}

class TestDerived : Test
{
     override void fun()
     {
         int a;
         int *b = &a;
     }
}
```

You get: `(11): Error: cannot take address of local `a` in 
`@safe` function `fun``. The override is not even marked as @safe 
and the compiler does not indicate that the function is @safe 
because it overrides a safe function. Anyway, I digress.

The point is, there is no way for a library owner to satisfy both 
people that want attributes and people that don't. If you do not 
put attributes on your code from the beginning, users of your 
class will not be able to call the super method from an 
attributed scope. If you put attributes on your methods, there is 
no way to bypass them in your overrides. I understand that if we 
would allow to relax the restrictions in overrides that would 
lead to the ability of calling unsafe code from safe contexts, 
but the current design makes it cumbersome to use classes with 
attributes. It just seems simpler to never use attributes at all 
(with classes).

Now, the entire point of this post is to ask what should we do in 
the case of: https://github.com/dlang/dmd/pull/14432. The story 
is: the methods of core.sync.condition can be made @nogc; the 
only reason why we did not do that is because we would throw some 
SyncErrors (which are allocated with the gc); the fix is trivial, 
we just use an abort function that does not throw anything, it 
just ends execution. However, now, if we mark the methods as 
@nogc we break downstream code (phobos as well) because suddenly 
those methods need to abide to new restrictions.  How do we get 
out of this stale mate?

Cheers,
RazvanN


More information about the Digitalmars-d mailing list